为什么参数通过 RDI、R10、R11 传递,而不是通过堆栈传递?

问题描述 投票:0回答:1

因此,我正在编写一个生成 mandelbrot 集的简单程序,它可以让您决定使用用 C++ 编写的函数还是用 assemlby 编写的函数来生成该集。主程序是用C#编写的。我使用的是带有 VS2022、x64 和 AMD 处理器的 Windows 10。

我将 7 个参数(一个字节*和六个整数)传递给汇编过程并尝试访问它们。前 4 个参数按预期通过 RCX、RDX、R9 和 R10 寄存器传递,但我无法访问其余 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 表达式通过单独线程中的委托调用 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 中显式声明调用约定不会改变参数的传递方式。

c# assembly x86-64 masm calling-convention
1个回答
0
投票

x64 调用约定在使用堆栈之前首先使用寄存器,因为寄存器要快得多(并且不必稍后移入寄存器,因为它们已经在寄存器中)。您可以在这里阅读更多内容:

© www.soinside.com 2019 - 2024. All rights reserved.