"undefined symbol rax, rbx, rcx, rdx" 在 MASM Visual Studio 中



以下是代码:

.386
.model flat, stdcall
.stack 4096
ExitProcess PROTO, dwExitCode:DWORD
.DATA
.code
Main proc
mov rax,0
mov rbx,0
mov rcx,0
mov rdx,0
mov al, 0F0H           ;using 8-bit register
mov bx, 1012H            ;using 16-bit register
mov ecx, 15284H          ;using 32-bit register

mov rdx, 3578815H        ;using 64-bit register

INVOKE ExitProcess, 0
main ENDP
END main

每当我运行这个时,它都会说:

未定义符号rax、rbx、rcx、rdx

但当我使用时它有效

.386
.model flat, stdcall
.stack 4096
ExitProcess PROTO, dwExitCode:DWORD
.DATA
.code
Main proc
mov eax,0
mov ebx,0
mov ecx,0
mov edx,0
mov al, 0F0H           ;using 8-bit register
mov bx, 1012H            ;using 16-bit register
mov ecx, 15284H          ;using 32-bit register  

mov edx, 3578815H        ;using 64-bit register  
INVOKE ExitProcess, 0
main ENDP
END main

我使用的是x86配置。x64对我不起作用。有人能告诉我为什么RAX、RBX、RCX和RDX不起作用吗?

对于Visual Studio,64位构建将使用ML64.EXE而不是MASM.EXE。不要使用.386指令。ML64.EXE没有.model指令,因为64位调用约定是固定的。

您不能在32位代码中使用64位寄存器

在16位模式中,32位寄存器可用于前缀为66h67h的机器代码。因此,16位和32位代码都可以使用类似movzx ax, byte ptr [ecx]的指令(当然,假设代码运行在386或更新版本上,因此.model 386会告诉汇编程序,它应该允许您编写这样的代码(。

但对于x86-64,在32位模式中没有一个未使用的字节可以用作前缀,因此AMD64架构师不得不采取不同的做法。x86-64的新功能仅在64位模式下可用,而不是在32位兼容模式下可用。

他们选择的实际机制是删除inc regdec reg的1字节编码,并将这些0x4?字节重新用作REX前缀,包括一个用于区分add eax, ecxadd rax, rcx的Width位,以及3个用于寄存器号的额外位,从而允许访问r8-r15以获取add r8d, [r9 + r10]等指令。


Ashttps://wiki.osdev.org/X86-64_Instruction_Encoding#REX_prefix说,REX前缀仅在长模式下可用

有趣的事实:如果您尝试在32位模式下使用CPU执行64位机器代码(例如,在源代码中使用NASMbits 64并与nasm -fwin32组合(,REX前缀将解码为incdec指令。

你可以玩一些有趣的把戏,比如制作机器代码,根据它在什么模式下执行,以3种不同的方式运行。例如,x86-32/x86-64多语言机器代码片段,它在运行时检测64位模式。此外,一个3向代码高尔夫答案显示了同一代码的3种不同的反汇编方式。

相关内容

  • 没有找到相关文章

最新更新