【问题标题】:How to identify the calling conventions within assembly code如何识别汇编代码中的调用约定
【发布时间】:2015-05-05 19:29:52
【问题描述】:

我有三个汇编代码片段,我应该为每个片段确定正确的调用约定(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

【问题讨论】:

  • wtb 在 stackoverflow 上的汇编代码高亮 :(
  • add esp... 不是唯一的方法,ret also works
  • 所以在ret的情况下,返回地址从堆栈中弹出并放入eip。所以由调用者来清理堆栈,对吧?
  • 使用 stdcall 和 fastcall 调用约定,从堆栈中弹出参数是函数的工作。您的一个函数在堆栈上没有任何参数,其中一个从堆栈中弹出参数,其中一个不从堆栈中弹出参数。

标签: assembly nasm calling-convention


【解决方案1】:

first Fragment 是 fastcall 调用约定 因为该过程使用了寄存器(EAX,EDX)而没有为其分配值 - 这意味着调用者使用寄存器来传递参数 - 就像在行中

mov [ ebp-0x4 ] , eax

第二个 Fragment 是 stdcall 调用约定,因为该过程从参数中清除了堆栈

ret 0xC

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

ret

每一项的快速标记将是:

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

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

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

有关更多信息,请参阅 wiki

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

【讨论】:

    【解决方案2】:

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

    要发现fastcall,您只需要找到未初始化就已使用的寄存器。您可以在第一个片段中看到这一点:eaxedx 都没有被初始化。这就是fastcall

    剩下的一定是cdecl,但当然你可以看到它正在通过ebp+0x8ebp+0xC访问返回地址上方的参数,它并没有删除它们。

    【讨论】:

    • 谢谢,非常清楚。我非常专注于添加指令,而忘记了其余的。
    猜你喜欢
    • 2019-12-10
    • 2013-12-13
    • 1970-01-01
    • 1970-01-01
    • 2015-04-08
    • 1970-01-01
    • 2017-01-19
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多