我有一个带签名的功能:
extern "C" int foo(int a, int b, int c, int d, int e);
实际上是用汇编语言编写的。
使用ml(32位),使用标准调用约定,你几乎可以编写
.code
foo PROC a: DWORD, b: DWORD ,c: DWORD, d: DWORD, e: DWORD
mov eax, d
mov ebx, e
并开始使用这些标签来访问您的参数
使用ml64(64位),fastcall是唯一可用的约定。我可以轻松访问存储在寄存器中的第一个参数,但访问堆栈中的参数(本例中为e
):我试过了
.code
foo PROC a: DWORD, b: DWORD ,c: DWORD, d: DWORD, e: DWORD
和
.code
foo PROC e: DWORD
但e
中的值是垃圾。
我发现如果直接使用堆栈地址,我会找到值。
.code
foo PROC e: DWORD
mov eax, r9 ; d
mov ebx, DWORD PTR[rbp + 48] ; e
还有其他办法吗?
答案 0 :(得分:4)
文档解释了所有内容...在Windows中,前四个整数参数在寄存器RCX
,RDX
,R8
,R9
和XMM0
中的浮点传递1}},XMM1
,XMM2
,XMM3
,在阴影空间上方的堆栈上传递的参数超过四个。对于Unix类型的OS,它有点不同。
所以,你的例子是正确的 - mov ebx, DWORD PTR[rbp + 48] ; e
阴影空间= 32 +保存rbp = 40 +第5参数= 48
答案 1 :(得分:0)
给定的
extern "C" int foo(int a, int b, int c, int d, int e);
我发现如果
,Visual Studio 2010不会保存基本指针RBP
.code
foo PROC
但是如果
则保存基指针.code
foo PROC e: DWORD
更高版本(vs2015)不允许使用第二个代码。
There is an optional optimization in x64 systems where RBP
is not used(发现困难的方法)。它说:
常规使用%rbp作为堆栈帧的帧指针 可以通过使用%rsp(堆栈指针)来索引到 堆栈框架。这种技术在序言中保存了两条指令 结语并制作一个额外的通用寄存器(%rbp) 可用。
因此有可能foo PROC e: DWORD
无法编译(vs2015)或foo PROC
崩溃,因为RBP为空。
检索堆栈参数的正确方法是使用
给出的RSP
堆栈指针
RBP = RSP + 8 * num_saved_reg
其中num_saved_reg
是PROC指令中指定的寄存器数。所以当没有保存rbp时(否则添加8)
PROC -> DWORD PTR[rsp + 40]
PROC use RDI -> DWORD PTR[rsp + 40 + 8]
PROC use RDI RSI RBX -> DWORD PTR[rsp + 40 + 24]