混合 c++ 和汇编不能将多个参数从C++函数传递到程序集

Mixing c++ and assembly cant pass multiple paramaters from C++ function to assembly

本文关键字:函数 C++ 程序集 参数 c++ 汇编 不能 混合      更新时间:2023-10-16

我对将参数从 c++ 函数传递到程序集感到沮丧。我在谷歌上找不到任何有帮助的东西,真的很想得到你的帮助。我正在使用Visual Studio 2017和masm来编译我的汇编代码。

这是我的 c++ 文件的简化版本,我在其中调用汇编过程set_clock

int main()
{
TimeInfo localTime;
char clock[4] = { 0,0,0,0 };
set_clock(clock,&localTime); 
system("pause");
return 0;
}

我在汇编文件中遇到问题。我不知道为什么传递给函数的第二个参数变得很大。我正在离开我的教科书,其中显示了类似的代码,带有 PROC 后跟参数。我不知道为什么第一个参数成功传递,第二个参数没有。有人可以告诉我传递多个参数的正确方法吗?

.code
set_clock PROC, 
array:qword,address:qword
mov rdx,array   ; works fine memory address: 0x1052440000616
mov rdi,address ; value of rdi is 14757395258967641292
mov al, [rdx] 
mov [rdi],al    ; ERROR: cant access that memory location
ret
set_clock ENDP
END

MASM的高级废话正在咬你的屁股。x64 Windows 通过rcxrdxr8r9中的前4 个参数(对于这 4 个整数/指针中的任何一个(。

mov rdx,array
mov rdi,address

组装到

mov  rdx, rcx    ; clobber 2nd arg with a copy of the 1st
mov  rdi, rdx    ; copy array again

使用反汇编器自行检查。 如果汇编程序宏发生任何奇怪的事情,通过反汇编或使用调试器反汇编而不是源模式来检查真实的机器代码总是一个好主意。


我不确定为什么这会导致无法访问的内存位置。 如果两个参数确实都是指向局部变量的指针,那么它应该只是加载并存储回相同的堆栈位置。 但是,如果char clock[4]是静态存储中的const,则它可能位于只读内存页中,这将解释存储失败。

无论哪种方式,请使用调试器并找出答案。


顺便说一句,rdi是 x64 Windows 约定中的调用保留(又名非易失性(寄存器。(https://msdn.microsoft.com/en-us/library/9z1stfyw.aspx(。 对暂存注册使用调用破坏寄存器,除非您用完并需要保存/恢复一些保留的呼叫注册。 另请参阅 Agner Fog 的调用约定文档 (http://agner.org/optimize/(,以及 x86 标签 wiki 中的其他链接。

它在 x86-64 System V 中被调用破坏,它也在不同的寄存器中传递参数。 也许您正在查看另一个示例?


希望修复版本,使用movzx来避免在加载字节时对 RAX 的错误依赖。

set_clock PROC, 
array:qword,address:qword
movzx    eax, byte ptr [array] 
mov      [address], al
ret
set_clock ENDP

我不使用 MASM,但我认为array:qword使array成为rcx的别名。 或者,您可以跳过声明参数,而直接使用rcxrdx,并用注释记录它。 这对每个人都会更容易理解。

你绝对不希望无用的mov reg,reg指令弄乱你的代码;如果你首先用asm编写,浪费的指令会削减你得到的任何加速。