Assembly-了解一个函数调用,它在ret值前后使用EAX

问题描述 投票:0回答:1

我一直在尝试挂钩一个大多数由编译器优化的函数,它在调用之前初始化EAX,并将其返回值存储在EAX中。

这里有一些代码,

mov eax,dword ptr ds:[0xA6DD08]
push 0x3DC                     
add eax,0x800                  
call 0x48A2B4  
mov esi,eax     

起初,0xA6DD08是指向内存中某些数据的指针,但是一旦添加0x800,EAX仅指向zero的值,但是接下来的几个DWORD存储指针或数据数组的指针。函数本身的目的是查找并返回一个特定对象,该对象的DWORD变量等于给定的0x3DC。

[当使用__ asm从我的dll调用该函数时,它工作正常,但我试图用c ++编写它,类似

Class1*  pClass = reinterpret_cast<Class1*(__stdcall*)(DWORD)>(0x48A2B4)(988);

我相信,根据我的阅读,只有__ stdcall使用EAX来存储它的返回值,这就是为什么我选择__ stdcall调用约定的原因,但我不理解EAX]的目的在调用函数之前。

c++ assembly visual-c++ x86 calling-convention
1个回答
0
投票

除非EAX是被调用函数的输入,否则add eax,0x800之前的[call是没有意义的。

[在EAX中传递1 arg,然后在堆栈中传递另一个args对我来说就像GCC的regparm=1 calling convention。或者,如果在此之前设置了其他规则,则regparm=1以EAX,EDX和ECX的顺序传递。

Linux内核的32位x86构建通常是用regparm=3构建的,但是用户空间GNU / Linux代码通常遵循笨拙的旧i386 System V约定,该约定将堆栈中的所有args传递。

根据-mregparm=3,其他一些晦涩的调用约定也在EAX中传递了第一个参数:

实际上,all

x86调用约定对整数args进行了全面的处理。同样是x86-64约定。请参阅register调用约定指南。
© www.soinside.com 2019 - 2024. All rights reserved.