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

时间:2015-05-05 19:29:53

标签: assembly nasm calling-convention

我有三个汇编代码片段,我应该为每个片段确定正确的调用约定(CDECL,STDCALL,FASTCALL)。为了识别调用约定,我正在搜索堆栈清理器,它是调用者或被调用者。但是,如果我找不到我认为的清洁代码看起来像'添加esp,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

2 个答案:

答案 0 :(得分:2)

第一个Fragment是fastcall调用约定 因为该过程使用了寄存器(EAX,EDX)而没有为其赋值 - 这意味着调用者使用寄存器来传递参数 - 比如行

mov [ ebp-0x4 ] , eax

第二个片段是stdcall调用约定,因为该过程从参数

清除了堆栈
ret 0xC

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

ret

每个人的快速标记将是:

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

stdcall:被调用者必须清理堆栈。

cdecl:调用者必须清理堆栈。

有关更多信息,请参阅wiki

http://en.wikipedia.org/wiki/X86_calling_conventions

答案 1 :(得分:0)

由于返回地址在路上,因此callee清理的典型方法是ret X指令(其中X是要删除的参数字节数)。因此,你的第二个例子是被调用者清理,即。 stdcall

要发现fastcall,您只需找到未经初始化使用的寄存器。您可以在第一个片段中看到此内容:eaxedx都未初始化。那就是fastcall

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