x86_64 汇编器的 gcc 错误(操作码 0x83 cmp m64/imm8)
Posted
技术标签:
【中文标题】x86_64 汇编器的 gcc 错误(操作码 0x83 cmp m64/imm8)【英文标题】:gcc error for x86_64 assembler (opcode 0x83 cmp m64/imm8) 【发布时间】:2020-06-14 06:04:25 【问题描述】:当我尝试编译时
int main(void)
__asm__("cmp $0x1,0x555557e20b58");
return 0;
我明白了
main.cpp: Assembler messages:
main.cpp:6: Error: operand type mismatch for `cmp'
编译命令是“gcc main.cpp -o main”。它适用于 m32 值,例如"asm("cmp $0x1,0x555557e2");".
根据this X86 Opcode and Instruction Reference,有一个操作码为0x83的命令,modrm_reg:7,称为“CMP”,第一个参数:r/m16/32/64,第二个参数:imm8,描述:“比较两个操作数”。为什么 gcc 找不到呢?我尝试使用 CMPQ,但无济于事。
我尝试编译这条指令的原因是我想查看机器代码。
这来自“英特尔® 64 和 IA-32 架构软件开发人员手册”:
REX.W + 83 /7 ib CMP r/m64, imm8 MI Valid N.E. Compare imm8 with r/m64.
所以对于机器代码,我希望
第一个字节为 0x48 (REX.W) 和 第二个字节为操作码 0x83。 对于第 3 个字节 (ModR/M),我迷路了:手册上说“/digit - 0 到 7 之间的数字表示指令的 ModR/M 字节仅使用 r/m(寄存器或内存)操作数。reg 字段包含提供扩展的数字指令的操作码。”因此,据此,我理解 modrm_reg = 7。但是 r/m 的含义是什么?
字节 4 - 11 将是 8 字节值 字节 12 比较 imm8 值【问题讨论】:
x86指令只有1个立即数,只有movabs可以接收64位立即数,其他最多32位立即数 @phuclv,问题不在于直接,而在于寻址模式。 您还需要一个操作数大小后缀,因为cmp $1, addr
无法推断您是否要比较字节、字等。如果您想要r/m64
形式,则使用cmpq
。
【参考方案1】:
x86_64 中没有指定 64 位绝对地址的指令格式——在 32 位模式下指定 32 位绝对地址的 r/m 编码用于 RIP 相对寻址——一个 32-指令指针的位(有符号)位移。
所以如果你想在 64 位模式下做这样的事情,你需要类似的东西
__asm__("cmp $0x1,symbol(%rip)");
并在链接器中安排将代码链接到固定地址(无 ASLR),并将 symbol
定义为 0x555557e20b58。
【讨论】:
如果他真的想访问一个绝对地址,最好将它加载到一个寄存器中并取消引用它,而不是使用 rip-relative 寻址。 有一组移动指令允许使用 64 位地址:将内存移入/移出 al/ax/eax/rax。 请注意,x86_64 中有绝对寻址模式,但也只需要 32 位位移。以上是关于x86_64 汇编器的 gcc 错误(操作码 0x83 cmp m64/imm8)的主要内容,如果未能解决你的问题,请参考以下文章