汇编动态调用API的奇葩问题,内详!

shier2817 2014-12-25 04:53:45
这里拿 HeapAlloc 申请堆内存这个来举例说吧:
我已经动态的获取到他的函数地址了(VA),我将其放入一个结构声明中(因为我要用好几个API,都是动态获取到的),同时我进行了函数声明,大致如下:

_qHeapAlloc typedef proto stdcall :dword, :dword, :dword
_pHeapAlloc typedef ptr _qHeapAlloc

myAPI STRUCT
DefaultHeap dd ? ;这个是默认堆,我也已经获取好了。
HeapAlloc _pHeapAlloc ?
…… 还有其他的API
myAPI ENDS

然后我开始调用:

assume ebx:ptr myAPI ;假设我给存储的结构体已经放入ebx了。
mov ecx, 123 ;--------------注意这里,实际没什么用,但正是我要问的问题。。。
invoke [ebx].HeapAlloc, [ebx].DefaultHeap, 0, edx ;假设我要申请的尺寸在edx中
;这里返回的eax是正确的,我已经测试过是个有效的内存指针,读写都没问题,这不是我要问的,所以这里不去管他;

mov eax, ecx ;-------------------这里我晕了,不应该是123吗?结果竟然是好几万的数字。。

我就想问问这个ecx为什么会变化了呢???照理说这是个STDCALL的API啊,堆栈不是API内部就给平衡了么?
而且反汇编大概如下:

push edx
push 00000000h
push dword ptr [ebx]
call dword ptr [ebx+04h]

这也没有任何地方修改了ecx啊???其实我还测试过,不但ecx变了,edx也会变……
请教前辈,这是啥原因?我该如何解决???
(我说的解决不是在调用前push ecx,完事了再pop回来哦,因为直接调用API的时候也没这些事儿啊,是不是我声明原型哪里写的不对?)

万分感激哦!!!
...全文
153 4 打赏 收藏 转发到动态 举报
写回复
用AI写文章
4 条回复
切换为时间正序
请发表友善的回复…
发表回复
「已注销」 2014-12-26
  • 打赏
  • 举报
回复
嗯,懂了,这个是我孤陋寡闻了。。。不过,挺坑爹个事儿哦。。。结贴了。。
zara 2014-12-26
  • 打赏
  • 举报
回复
eax 作为结果返回,其内容几乎是必变,易失性是肯定的了。
对易失寄存器,一般用的是方法 1. 吧,push/pop 指令相对最简单。
「已注销」 2014-12-25
  • 打赏
  • 举报
回复
晕,我百度了下这个术语,确实是这么回事。。。 这还能让人用汇编不啊??? 我在我自己写的子程序里面,对可能用到的寄存器全都进行了保存。。。为啥windows的API就非要乱修改呢? 对于ecx和edx(eax一般都是用作返回倒不太要紧,而且我查到的资料描述,易失性寄存器貌似不包括eax哦),是不是我只有3种方法: 1、调用API前如果他们的值是重要的,就要自己入栈保护; 2、调用API前如果他们的值是重要的,可以考虑写到局部变量里; 3、干脆用别的寄存器好了,特别是在循环过程中; 还有别的招儿么???
  • 打赏
  • 举报
回复
eax、ecx、edx是“易失”寄存器,这些寄存器的内容可能在各类编译器生成的函数、系统API调用内部被修改,如果要保持的话需要你自己保存/恢复。

21,458

社区成员

发帖
与我相关
我的任务
社区描述
汇编语言(Assembly Language)是任何一种用于电子计算机、微处理器、微控制器或其他可编程器件的低级语言,亦称为符号语言。
社区管理员
  • 汇编语言
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧