这里拿 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的时候也没这些事儿啊,是不是我声明原型哪里写的不对?)
万分感激哦!!!
------解决思路----------------------
eax、ecx、edx是“易失”寄存器,这些寄存器的内容可能在各类编译器生成的函数、系统API调用内部被修改,如果要保持的话需要你自己保存/恢复。
------解决思路----------------------
eax 作为结果返回,其内容几乎是必变,易失性是肯定的了。
对易失寄存器,一般用的是方法 1. 吧,push/pop 指令相对最简单。