x86 32位操作码,在x86-x64中有所不同或完全删除

Dy *_*der 8 x86 assembly x86-64 cpu-architecture opcode

我在x86-x64中查找了维基百科的x86向后兼容性,它说:

x86-64完全向后兼容16位和32位x86代码.因为完整的x86 16位和32位指令集仍然在硬件中实现而没有任何干预仿真,现有的x86可执行文件运行时没有兼容性或性能损失而重新编码以利用处理器设计的新功能的现有应用程序可以实现性能改进.

所以我测试了一些指令,看看有些指令实际上产生完全不同的操作码(而不仅仅是应用前缀),例如:INC/DEC.看(x86):

\ x40 inc eax
\x48 dec eax

在x86-x64中组装相同的产品时:

\ xff\xc0 inc eax

\ xff\xc8 dec eax

我试图弄清楚其他指令的原因和更多例子,这些指令具有产生不同操作码的相同症状.我熟悉x86-x64中的push,pop,call,ret,enter和leave不可用32位.

Pet*_*des 9

几乎所有两种模式下可用的指令在两种模式下都具有相同的操作码.

删除说明:

  • 二进制编码的十进制数字,例如AAM(乘法后的ASCII调整),用于在每个4位半的两个基数为10的数字寄存器上执行正常的二进制加/子/ mul/div后修复二进制编码的十进制数.无论如何,他们跑得很慢,没有被使用.将数字存储为二进制整数而不是BCD是很普遍的.
  • /流行CS/ DS/ ES/ SS被拆除.push/pop FS和GS仍然有效(这两个段在长模式下仍然可以具有非零基数). mov Sreg, r32并且mov r32, Sreg仍可用于"neutered"段寄存器,因此您可以使用临时整数寄存器来模拟推/弹.CS仍然很重要; 远程跳转到另一个代码段可以切换到32位模式,其他代码段仍然需要有效的段描述符.
  • ARPL这样的其他模糊部分:调整段选择器的RPL字段.它实际上只是一个位域钳位和整数寄存器的设置标志指令,所以可以通过内核可能需要它的罕见地方的一些其他指令来模拟.
  • 也许是编译器从未在32位代码中使用的其他一些模糊或特权指令.(并非编译器发出上述任何一种,没有内在函数或内联asm).

删除(重新调整)一些仍然可用的指令的编码:在你的情况下,32位可以使用inc r32单字节操作码(0x40 +寄存器号).64位模式仅具有inc r/m32编码,其中要递增的寄存器由第2个字节指定.(在这种情况下,0x4x字节被重新用作REX前缀字节).

英特尔公司的insn引用(按照链接在x86标签维基,或)显示以下inc:

Opcode   Instruction Op/   64-Bit   Compat/
                     En     Mode    Leg mode

FF /0   INC r/m32     M     Valid     Valid     Increment r/m doubleword by 1.
40+ rd  INC r32       O      N.E.     Valid     Increment doubleword register by 1.
Run Code Online (Sandbox Code Playgroud)

NE表示不可编码.Op/En列描述了如何编码操作数.


Jan Hubicka的AMD64 ISA概述简要描述了REX前缀的单字节inc/dec操作码的重新利用,默认操作数大小以及立即数据仍为32位. movabs可用于加载64位立即数,或从64位绝对地址加载/存储.

AMD的AMD64手册,第2.5.11节重新分配的操作码有一个很短的表.它只列出:

  • 4x inc/dec r32 转为REX前缀
  • 63 ARPLMOVSXD当与REX.W = 1(这意味着REX前缀中的W位= 1)一起使用时,它变为(将qword符号扩展为qword).

早期的AMD64和Intel EMT64 CPU SAHF/LAHF在长模式下被遗漏,但后来使用与32位相同的操作码重新添加了该指令.该表还没有列出被删除的指令(BCD指令和其他指令),这些指令已被删除,以便为将来可能的扩展腾出空间.


他们可以简化很多事情,并使x86-64成为更好的清洁指令集,为未来扩展提供更多空间,但与32位的差异意味着更多的解码器晶体管.没有机器指令移动到64位的不同操作码.

多个机器指令通常共享相同的asm助记符,mov是最重载的.有加载,存储,具有立即常量的mov,移动到/来自段寄存器,全部在8位和32位.(16位是带有操作数大小前缀的32位,对于带有REX前缀的64位是相同的.)有一个用于从64位绝对地址加载RAX的特殊操作码.还有一个特殊的操作码,用于将64位立即数加载到寄存器中.(AT&T语法调用这个movabs,但它仍然只是在英特尔/ NASM中移动)


Eld*_*Bug 5

该陈述是真实的,但有些误导.x86-64体系结构向后兼容x86,但32位指令集与64位指令集不兼容.

您可以使用兼容模式在x86-64 CPU上运行x86代码.实际上,由于CPU应该是透明的x86到x86代码,所以它恰恰相反:当你想运行x86-64代码时,你进入64位模式(长模式).这意味着您无法同时运行两者,但可以从一种模式切换到另一种模式.