【问题标题】:How to know where's the first function argument?如何知道第一个函数参数在哪里?
【发布时间】:2014-02-07 01:58:44
【问题描述】:

我只是想知道,如果我有这个 ASM 功能:

PUSH EBP
MOV EBP, ESP
SUB ESP, 8
LEAVE
RETN 8

什么都不做,只接受两个 4 字节的参数。似乎第一个参数位于EBP+8,第二个参数位于EBP+12。但是,怎么知道呢?因为如果函数采用三个 4 字节参数,那么第三个将位于 EBP+16。第一个参数是否总是在EBP+8,然后我只需添加参数大小即可获得下一个?如果是,为什么是 8 个?

提前致谢。

【问题讨论】:

    标签: function assembly x86 arguments cpu-registers


    【解决方案1】:

    它是 8,因为通常,EBP+0 = 调用者保存的 EBP,EBP+4 = 返回地址,EBP+8 = 第一个基于堆栈的参数。

    此外,像这样的偏移量通常以十六进制值表示,因此第二个基于堆栈的参数将位于 EBP+C,第三个将位于 EBP+10。

    推断函数调用约定的一个好方法(虽然不是 100%)是查看函数的调用者如何在调用函数之前(以及在函数返回之后)准备寄存器和/或堆栈.

    【讨论】:

    • 感谢您的回答。我会标记 Necrolis 的答案,因为他首先回答了,但两者都对我有帮助! +1。另外,我正在使用 VC++ 编译器中的 __asm 语句执行该 ASM 代码,它会自动将所有数值转换为十六进制值,这就是我使用 8、12、16 的原因。再次感谢!
    【解决方案2】:

    第一个 stack 参数在使用堆栈帧时始终位于 [EBP+8],但调用约定可以在寄存器(通用和 SIMD)和堆栈中传递参数。

    您的示例假设您使用标准化约定,例如 __stdcall__cdecl,但 __fastcall 和 VC++13 的新 __vectorcall 中的参数将分别用于通用和 SIMD 寄存器(以及寄存器本身根据 ABI Sys-V 与 MS 不同)。

    【讨论】:

    • 好了,我这就够了!我正在使用__stdcall 约定。谢谢!
    【解决方案3】:

    函数参数的布局取决于此函数使用的调用约定。调用约定可以是函数创建者能够想象的任何东西。

    【讨论】:

    • 谢谢,但这对我帮助不大。
    • 您应该更具体地了解您想知道什么以获得更好的答案。
    • 对不起,但我想我是具体的。我怎么知道函数的第一个参数在哪里?
    • 回想起来,我想说你可以指定问题是关于__stdcall
    • 好的,抱歉。也谢谢你的回答。
    猜你喜欢
    • 2022-12-03
    • 2011-01-30
    • 2011-03-21
    • 2012-12-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多