我正在尝试为使用64位寄存器的Intel语法编写的x86_64汇编一些汇编源代码。我使用以下命令行标志:
yasm foo.asm -a x86 -m amd64
我一直收到如下错误:
warning: `rbp' is a register in 64-bit mode
foo.asm:23: error: undefined symbol `rbp' (first use)
所以,我在stackoverflow上看到了一个similar question,以及网上的numerous resources,表明这个问题可以通过指定“BITS”指令来解决,特别是:
BITS 64
问题是,我不清楚这甚至意味着什么。我不明白什么是“指令”。这似乎是你需要在汇编代码中指定的东西。但在这种情况下,我不控制代码,所以我只是想找到一个命令行标志来组装它。
有没有办法在命令行标志中指定BITS
指令,我可以传递给yasm?
使用-felf64
将x86-64代码组装成64位ELF .o
。
如果您正在制作平面二进制文件(不是.o
或.obj
),请在文件顶部使用BITS 64
。否则避免它,您通常不希望将64位机器代码放入32位.o
;构建时错误更好。
尽管文档in the manual,YASM的-a x86 -m amd64
选项不会覆盖默认的-fbin
平面二进制输出格式的默认值,即组装假设代码将以16位模式执行。 (完全像NASM)。
使用-m x86
可以防止文件中的-felf64
或BITS 64
工作。它是YASM的CPU功能限制支持的一部分,可以帮助阻止您意外使用目标CPU不支持的ISA功能。 (例如,CPU Conroe AMD
启用SSSE3和AMD64指令,如syscall
,同时禁用SSE4和AVX。默认情况下没有限制。)
BITS 16
是-fbin
的默认模式。
汇编程序必须知道CPU期望执行代码的模式。例如,mov eax,ecx
是32位模式下的89 C8
,但是16位模式下的66 89 C8
(操作数大小覆盖前缀,然后是相同的操作码+ modrm)对于32位模式)。
通常,64位操作数大小和地址大小以及64位寄存器只能在64位模式下编码,因此当汇编程序生成将在16-执行的代码时,尝试使用rbp
汇编代码时出错位模式。
以16位模式启动的引导加载程序可能会切换到32位和/或64位模式,因此在切换到32位或64位的BITS 32
的跳转目标前需要一个BITS 64
或jmp far
指令模式。
这是BITS指令的正常用例。不幸的是,就像NASM一样,似乎没有一个命令行选项可以在你选择的模式中组装一个平面二进制文件。如果您可以将inc eax
放入文件并获取66 40
,40
或FF C0
而无需编辑文件,只需使用命令行选项,这将是很酷的,但我们不能。
如果我理解正确,你的问题是:如何“激活”64位模式?
这很简单。
如果您的代码是:
mov rax, [rbp - 2]
mov rbx, rax
syscall ;just to call some or for end of code
然后将其更改为:
bits 64
mov rax, [rbp - 2]
mov rbx, rax
syscall ;just to call some or for end of code
简单地说,将“位64”放在代码的开头!