Assembly 如何在汇编代码中识别调用约定

Assembly 如何在汇编代码中识别调用约定,assembly,nasm,calling-convention,Assembly,Nasm,Calling Convention,我有三个汇编代码片段,我应该为每个片段确定正确的调用约定(CDECL、STDCALL、FASTCALL)。为了识别调用约定,我正在搜索堆栈清理器,它是调用者或被调用者。但是,如果我找不到像“AddESP,8”这样的清理代码,该怎么办。我的方法错了吗。我必须搜索其他呼叫约定特征吗?下面是代码片段 片段1 push ebp mov ebp , esp sub esp , 0x8 mov [ ebp-0x4 ] , eax mov [ ebp-0x8 ] , edx mov eax , [ ebp-0

我有三个汇编代码片段,我应该为每个片段确定正确的调用约定(CDECL、STDCALL、FASTCALL)。为了识别调用约定,我正在搜索堆栈清理器,它是调用者或被调用者。但是,如果我找不到像“AddESP,8”这样的清理代码,该怎么办。我的方法错了吗。我必须搜索其他呼叫约定特征吗?下面是代码片段

片段1

push ebp
mov ebp , esp
sub esp , 0x8
mov [ ebp-0x4 ] , eax
mov [ ebp-0x8 ] , edx
mov eax , [ ebp-0x8 ]
mov edx , [ ebp-0x4 ]
add edx , eax
mov eax , ecx
add eax , edx
leave
ret
片段2

push ebp
mov ebp , esp
mov eax , [ ebp+0xC]
mov edx , [ ebp+0x8 ]
add edx , eax
mov eax , [ ebp+0x10 ]
add eax , edx
pop ebp
ret 0xC
片段3

push ebp
mov ebp , esp
mov eax , [ ebp+0xC]
mov edx , [ ebp+0x8 ]
add edx , eax
mov eax , [ ebp+0x10 ]
add eax , edx
pop ebp
ret

由于返回地址有阻碍,被调用方清理的典型方法是
ret X
指令(其中
X
是要删除的参数字节数)。因此,您的第二个示例被称为清理,即stdcall

要发现
fastcall
,您只需找到未初始化的寄存器即可。您可以在第一个片段中看到这一点:
eax
edx
都未初始化。这就是
fastcall


剩下的必须是
cdecl
,但您当然可以看到它正在通过
ebp+0x8
ebp+0xC
访问返回地址上方的参数,并且它不会删除它们。

第一个片段是fastcall调用约定 因为过程使用了寄存器(EAX,EDX),而没有给它赋值——这意味着调用者使用寄存器来传递参数——就像一行一样

mov [ ebp-0x4 ] , eax
第二个片段是stdcall调用约定,因为该过程清除了堆栈中的参数

ret 0xC
ret
第三个片段是cdecl调用约定,因为过程从堆栈中获取了参数,但没有清除堆栈中的参数

ret 0xC
ret
每个项目的快速标记为:

fastcall:调用方使用寄存器传递前两个参数

stdcall:被调用方必须清理堆栈

cdecl:调用方必须清理堆栈

有关更多信息,请参阅wiki


stackoverflow上汇编程序代码的wtb突出显示:(
add esp..
不是唯一的方法,因此在
ret
的情况下,返回地址会从堆栈中弹出并放入
eip
。因此,由调用方清理堆栈,对吗?使用stdcall和fastcall调用约定,函数的任务是从堆栈中弹出参数。您的函数之一没有任何参数堆栈上的参数,其中一个从堆栈中弹出参数,另一个不从堆栈中弹出参数。谢谢,非常清楚。我太专注于add指令了,而忘记了其余的。