简体   繁体   English

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

[英]Retrieve arguments of a x64 masm assembly procedure

I have a function with the signature : 我有一个带签名的功能:

extern "C" int foo(int a, int b, int c, int d, int e);

which is in fact written in assembly. 实际上是用汇编语言写的。

With ml(32 bits), using standard calling convention you can pretty much write 使用ml(32位),使用标准调用约定,你几乎可以编写

.code
foo PROC a: DWORD, b: DWORD ,c: DWORD, d: DWORD, e: DWORD

     mov eax, d
     mov ebx, e

and start using those labels to access your arguments 并开始使用这些标签来访问您的参数

With ml64 (64 bits) the fastcall is the only convention available. 使用ml64(64位),fastcall是唯一可用的约定。 I have no trouble accessing the first arguments stored in the registers, but issues to access the ones in the stack ( e in this example): I tried 我可以轻松访问存储在寄存器中的第一个参数,但访问堆栈中的参数(本例中为e ):我尝试过

.code
foo PROC a: DWORD, b: DWORD ,c: DWORD, d: DWORD, e: DWORD

and

.code
foo PROC  e: DWORD

but the value in e is garbage. 但是e的值是垃圾。

I found that if I use the stack address directly I find the value. 我发现如果我直接使用堆栈地址,我会找到值。

.code
foo PROC  e: DWORD

     mov eax, r9                  ; d
     mov ebx, DWORD PTR[rbp + 48] ; e

Is there another way? 还有另外一种方法吗?

Documentation explains everything... In Windows, the first four integer parameters are passed in registers RCX , RDX , R8 , R9 and floating point in XMM0 , XMM1 , XMM2 , XMM3 , anything more than four parameters are passed on the stack above the shadow space. 文档解释了一切......在Windows中,前四个整数参数在寄存器RCXRDXR8R9XMM0XMM1XMM2XMM3浮点数中传递,任何超过四个参数都在阴影上方的堆栈上传递空间。 For Unix type OS's it is a bit different. 对于Unix类型的OS,它有点不同。

So, your example is correct - mov ebx, DWORD PTR[rbp + 48] ; e 所以,你的例子是正确的 - mov ebx, DWORD PTR[rbp + 48] ; e mov ebx, DWORD PTR[rbp + 48] ; e

Shadow space = 32 + saved rbp = 40 + 5th parameter = 48 阴影空间= 32 +保存rbp = 40 +第5参数= 48

given 特定

extern "C" int foo(int a, int b, int c, int d, int e);

I found out that visual studio 2010 doesn't save the base pointer RBP if 我发现visual studio 2010不保存基本指针RBP if

.code
foo PROC

but save the base pointer if 但保存基指针if

.code
foo PROC  e: DWORD

Later versions (vs2015) don't allow the second code. 更高版本(vs2015)不允许第二个代码。

There is an optional optimization in x64 systems where RBP is not used (found out the hard way). 在x64系统中有一个可选的优化,其中没有使用RBP (很难找到)。 It says : 它说 :

The conventional use of %rbp as a frame pointer for the stack frame may be avoided by using %rsp (the stack pointer) to index into the stack frame. 通过使用%rsp(堆栈指针)索引到堆栈帧,可以避免常规使用%rbp作为堆栈帧的帧指针。 This technique saves two instructions in the prologue and epilogue and makes one additional general-purpose register (%rbp) available. 这种技术在序言和结语中保存了两条指令,并提供了一个额外的通用寄存器(%rbp)。

So it is possible that either foo PROC e: DWORD doesnt compile (vs2015), or foo PROC crashes because RBP is null. 因此,有可能foo PROC e: DWORD没有编译(vs2015),或者foo PROC崩溃,因为RBP为空。

The correct way to retrieve stack arguments is to use the RSP stack pointer given that 检索堆栈参数的正确方法是使用给定的RSP堆栈指针

RBP = RSP + 8 * num_saved_reg

Where num_saved_reg is the number of registers specified in the PROC directive. 其中num_saved_reg是PROC指令中指定的寄存器数。 So when rbp is not saved (otherwise add 8) 所以当没有保存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]

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM