我只是想知道,如果我有这个ASM功能:
PUSH EBP
MOV EBP, ESP
SUB ESP, 8
LEAVE
RETN 8
它什么都不做,需要两个4字节的参数。似乎第一个参数位于EBP+8
,第二个参数位于EBP+12
。但是,怎么知道呢?因为如果函数需要三个4字节参数,那么第三个参数将在EBP+16
。第一个参数是否总是在EBP+8
,然后我只需要添加参数大小以获得下一个参数?如果是,为什么8?
提前致谢。
答案 0 :(得分:3)
它是8,因为通常,EBP + 0 =调用者保存的EBP,EBP + 4 =返回地址,EBP + 8 =第一个基于堆栈的参数。
此外,这样的偏移量通常以十六进制值表示,因此第二个基于堆栈的参数将为EBP + C,第三个将为EBP + 10.
推导函数的调用约定的一个好方法(不是100%)是看函数的调用者如何在调用函数之前准备寄存器和/或堆栈(也就是在函数返回之后)
答案 1 :(得分:2)
使用堆栈帧时,第一个堆栈参数将始终位于[EBP+8]
,但调用约定可以在两个寄存器(通用和SIMD)和堆栈中传递参数。
您的示例假设您使用标准化约定,例如__stdcall
,__cdecl
,但__fastcall
和VC ++ 13的新__vectorcall
中的参数将是通用的, SIMD寄存器(寄存器本身根据ABI Sys-V与MS的不同而不同)。
答案 2 :(得分:1)
函数参数的布局取决于用于此函数的调用约定。调用约定可以是函数创建者想象的任何东西。