由于某种原因,我需要 x86_64 操作码,并决定尝试使用汇编编译器找出它们。我写了一个简单的代码:
mov ax, 0
mov eax, 0
mov rax, 0
我有两个编译器:
- 8086模拟器(安卓)
- FASM(Windows)
我还在表格中搜索了https://looch-disasm.narod.ru/refe14.htm
他们给出了不同的结果(不同的错误)。简而言之:
-------|mov ax|mov eax|mov rax|
x86 Sim| B8 | Error | 66 B8 |
FASM | B8 | 66 B8 | Error |
第一个选项很可能是错误的(因为 8086 模拟器更像是一个调试器而不是编译器)。
那么“mov rax”的操作码是什么(是否有类似的简单表,仅适用于 x86_64)?
mov rax, <константа64бита>
-的操作码48 B8
:48
- 前缀 REX.W,表示“64 位操作”。仅在 64 位模式下可用!B8
- 操作“将常量加载到 AX/EAX/RAX”的操作码如果常数适合 32 位(有符号),则汇编器也可能输出
48 C7 C0
:48
- 前缀 REX.WC7
- 操作码“将常量加载到内存/寄存器中”C0
- 操作数字节:“AX/EAX/RAX 寄存器”原因:
48 C7 C0
它占用 7 个字节,并且48 B8
- 10 个字节。汇编程序选择较短的指令。x86 处理器有3 种二进制不兼容模式:16 位、32 位和 64 位。不同模式下机器码不同。您的汇编程序为16 位模式生成代码- 在此模式下 RAX 寄存器不可用。 64 位功能仅在 64 位模式下可用。
要强制 FASM 生成 64 位代码,请使用
use64
文件开头的指令。我对 8086 模拟器不太熟悉,但从名字上看它似乎只支持 16 位模式(就像原来的 8086 处理器一样)。
作为参考,64 位模式的正确操作码是:
mov ax, <константа16>
-66 B8
mov eax, <константа32>
-B8
mov rax, <константа64>
-48 B8
(或者48 C7 C0
)结果 0x66 0xB8 0x00 0x00 0xB8 0x00 0x00 0x00 0x00 0x48 0xC7 0xC0 0x00 0x00 0x00 0x00