如何识别汇编代码中的调用约定
How to identify the calling conventions within assembly code
我有三个汇编程序代码片段,我应该为每个片段确定正确的调用约定(CDECL、STDCALL、FASTCALL)。为了识别调用约定,我正在搜索作为调用者或被调用者的堆栈清理器。但是,如果我找不到我认为看起来像 'add 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
由于 return 地址挡道,被调用方清理的典型方法是 ret X
指令(其中 X
是要删除的参数字节数)。因此,您的第二个示例是被调用方清理,即。 stdcall
.
要发现fastcall
,您只需要找到未初始化就使用的寄存器。您可以在第一个片段中看到这一点:eax
和 edx
都没有被初始化。那就是 fastcall
.
剩下的一定是cdecl
,但是你当然可以看到它正在通过ebp+0x8
和ebp+0xC
访问return地址上方的参数,并且它不会删除它们。
第一个Fragment是fastcall调用约定
因为该过程使用了寄存器 (EAX,EDX) 而没有为其赋值——这意味着调用者使用寄存器来传递参数——就像在行
mov [ ebp-0x4 ] , eax
第二个片段是 stdcall 调用约定,因为该过程清除了参数的堆栈
ret 0xC
第三个片段是 cdecl 调用约定,因为该过程从堆栈中获取参数,但没有清除参数的堆栈
ret
每一项的快速评分为:
fastcall : 调用者使用寄存器传递前两个参数。
stdcall : 被调用方必须清理堆栈。
cdecl : 调用者必须清理堆栈。
有关详细信息,请参阅 wiki
我有三个汇编程序代码片段,我应该为每个片段确定正确的调用约定(CDECL、STDCALL、FASTCALL)。为了识别调用约定,我正在搜索作为调用者或被调用者的堆栈清理器。但是,如果我找不到我认为看起来像 'add 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
由于 return 地址挡道,被调用方清理的典型方法是 ret X
指令(其中 X
是要删除的参数字节数)。因此,您的第二个示例是被调用方清理,即。 stdcall
.
要发现fastcall
,您只需要找到未初始化就使用的寄存器。您可以在第一个片段中看到这一点:eax
和 edx
都没有被初始化。那就是 fastcall
.
剩下的一定是cdecl
,但是你当然可以看到它正在通过ebp+0x8
和ebp+0xC
访问return地址上方的参数,并且它不会删除它们。
第一个Fragment是fastcall调用约定 因为该过程使用了寄存器 (EAX,EDX) 而没有为其赋值——这意味着调用者使用寄存器来传递参数——就像在行
mov [ ebp-0x4 ] , eax
第二个片段是 stdcall 调用约定,因为该过程清除了参数的堆栈
ret 0xC
第三个片段是 cdecl 调用约定,因为该过程从堆栈中获取参数,但没有清除参数的堆栈
ret
每一项的快速评分为:
fastcall : 调用者使用寄存器传递前两个参数。
stdcall : 被调用方必须清理堆栈。
cdecl : 调用者必须清理堆栈。
有关详细信息,请参阅 wiki