4

我正在尝试为使用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 上看到了一个类似的问题,以及网络上的大量资源表明这个问题可以通过指定“BITS”指令来解决,特别是:

BITS 64

问题是,我不清楚这甚至意味着什么。我不明白什么是“指令”。这似乎是您需要在汇编代码本身中指定的内容。但是在这种情况下,我不控制代码,所以我只是试图找到一个命令行标志来组装它。

有没有办法BITS在我可以传递给 yasm 的命令行标志中指定指令?

4

2 回答 2

3

用于-felf64将 x86-64 代码组装成 64 位 ELF .o

如果您正在制作一个平面二进制文件(不是 a .oor .objBITS 64,请在文件顶部使用。否则避免它,您通常不希望将 64 位机器代码放入 32 位.o;构建时错误更好。


尽管手册中有文档,但YASM 的-a x86 -m amd64选项不会覆盖默认-fbin平面二进制输出格式的默认值,即在假设代码将以 16 位模式执行的情况下进行汇编。(就像 NASM 一样)。

使用-m x86 确实会阻止-felf64BITS 64在文件内工作。它是 YASM 的 CPU 功能限制支持的一部分,可以帮助防止您意外使用目标 CPU 不支持的 ISA 功能。(例如CPU Conroe AMD,启用 SSSE3 和 AMD64 等指令syscall,同时禁用 SSE4 和 AVX。默认为无限制。)


BITS 16是默认模式-fbin

汇编器必须知道 CPU 将在什么模式下执行您的代码。 例如,mov eax,ecx处于89 C832 位模式,但66 89 C8处于 16 位模式(操作数大小覆盖前缀,然后是与 32- 相同的操作码 + modrm位模式)。

64 位操作数大小和地址大小,以及一般的 64 位寄存器,只能在 64 位模式下编码,因此当rbp汇编器正在制作将以 16 位执行的代码时尝试汇编代码时会出错模式。

以 16 位模式启动的引导加载程序可能会切换到 32 和/或 64 位模式,因此您需要在跳转目标前面添加一个BITS 32or指令才能切换到 32 位或 64 位模式。BITS 64jmp far

是 BITS 指令的正常用例。不幸的是,像 NASM 一样,似乎没有一个命令行选项可以在您选择的模式下组装一个平面二进制文件。inc eax如果您可以放入一个文件并获取66 40, 40,或者不编辑文件,只使用命令行选项,那会很酷FF C0,但我们不能。

于 2019-02-22T19:11:29.947 回答
1

如果我理解正确,您的问题是:如何“激活”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”放在代码的开头!

于 2019-02-22T18:32:30.900 回答