提问人:mc jazda 提问时间:11/11/2023 最后编辑:mc jazda 更新时间:11/11/2023 访问量:115
为什么参数通过 RDI、R10、R11 传递,而不是通过堆栈传递?
Why are parameters passed via RDI, R10, R11 and not via stack?
问:
因此,我正在编写一个简单的程序来生成曼德布洛特集合,它允许您决定使用用 C++ 或 assemlby 编写的函数来生成该集合。主程序是用C#编写的。我正在使用带有 VS2022、x64 和 AMD 处理器的 Windows 10。
我正在将 7 个参数(一个字节* 和六个整数)传递给汇编过程并尝试访问它们。前 4 个参数按预期通过 RCX、RDX、R8 和 R9 寄存器传递,但我无法访问其余 3 个参数。在 [RSP+40] 处有一些随机数据。然后我尝试使用堆栈帧方法(因为我声明了 2 个局部变量),但值看起来仍然是随机的。我终于注意到我缺少的第 5、6 和 7 个参数是通过 RDI、R10 和 R11 传递的。有没有这样的调用约定,或者我只是遗漏了什么?
顺便说一句,大约半年前,当我在汇编中尝试参数传递时,它们按预期传递,这意味着:RCX、RDX、R8、R9,然后到堆栈上。
这是我的汇编函数的声明:
[DllImport(masmDllPath)]
private static extern void generateMandelMASM(
byte[] bmp, int rowCount, int rowNum, int resX, int resY, int alignment, int iterCount);
我正在使用 lambda expresion 通过委托在单独的线程中调用 C# 中提到的函数,如下所示:
for (int i = 0; i < settings.threadCount; i++)
{
int localIter = i; // Necessary because lambda captures by reference, not value
threads[i] = new Thread(() => generateMandel(bitmapRows[localIter], rowsPerThread[localIter],
rowOffset[localIter], settings.resX, settings.resY, alignment, settings.iterationCount));
}
组装程序的一部分:
.code
generateMandelMASM PROC
LOCAL alignment: DWORD
LOCAL rowCount: QWORD
;--------- Prologue ---------
push rbp
mov rbp, rsp
sub rbp, 16 ; subtracting number of locals * 8 bytes
mov r11d, dword ptr [rbp+50o]
mov alignment, r10d
在 DllImport 中显式声明调用约定不会更改参数的传递方式。
答:
x64 调用约定在使用堆栈之前首先使用寄存器,因为寄存器的速度要快得多(并且以后不必移动到寄存器中,因为它们已经在寄存器中)。您可以在此处阅读更多内容:
评论
第五个参数位于函数调用前的 [rsp+0x20]。在调用指令推送 rip 和函数 prologue 推送 rbp 后,第五个参数位于 [rbp+0x30]。
评论
sub rbp, 16
sub rbp, 16
下一个:Giltab CI 和图像平台
评论
push rbp
sub rbp, 16
rsp
rbp
[rbp+50o]
push rbp
sub rbp, 16
LOCAL
call