检索x64 masm程序集过程的参数

时间:2013-11-20 17:40:47

标签: c++ visual-studio-2010 assembly 64-bit masm

我有一个带签名的功能:

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

还有其他办法吗?

2 个答案:

答案 0 :(得分:4)

文档解释了所有内容...在Windows中,前四个整数参数在寄存器RCXRDXR8R9XMM0中的浮点传递1}},XMM1XMM2XMM3,在阴影空间上方的堆栈上传递的参数超过四个。对于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]