我正在尝试为使用 64位寄存器的英特尔语法编写的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
问题是,我甚至不清楚这是什么意思。我不明白什么是"指令"是。这似乎是你需要在汇编代码中指定的东西。但在这种情况下,我无法控制代码,所以我只是想找到一个命令行标志来组装它。
有没有办法在我可以传递给yasm的命令行标志中指定BITS
指令?
答案 0 :(得分:1)
使用-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之前的所有功能以及syscall
之类的AMD64指令,同时禁用SSE4和AVX。默认值为无限制。)
BITS 16
是-fbin
的默认模式。
汇编器必须知道CPU将在哪种模式下执行您的代码。例如,在32位模式下,mov eax,ecx
是89 C8
,但是{{ 1}}在16位模式下(操作数大小的覆盖前缀,然后是与32位模式相同的操作码+ modrm)。
64位操作数大小和地址大小以及通常的64位寄存器只能在64位模式下进行编码,因此在汇编器进行编译时尝试使用66 89 C8
汇编代码时出错将在16位模式下执行的代码。
以16位模式启动的引导加载程序可能会切换到32位和/或64位模式,因此您需要在跳转目标前面的rbp
或BITS 32
指令BITS 64
切换到32位或64位模式。
这是BITS指令的常规用例。不幸的是,像NASM一样,似乎没有命令行选项可以在您选择的模式下汇编平面二进制文件。如果您可以将jmp far
放入文件中并仅使用命令行选项而无需编辑文件就获得inc eax
,66 40
或40
,那就太好了,但是我们不能。
答案 1 :(得分:0)
如果我正确理解,您的问题是: 如何“激活” 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位放在代码的开头!