因此,我正在编写一个生成 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 中显式声明调用约定不会改变参数的传递方式。
x64 调用约定在使用堆栈之前首先使用寄存器,因为寄存器要快得多(并且不必稍后移入寄存器,因为它们已经在寄存器中)。您可以在这里阅读更多内容: