assembly - x86在x86-x64中不同或已完全删除的32位操作码

标签 assembly x86 x86-64 cpu-architecture opcode

我在Wikipedia中查找了x86-x64中的x86向后兼容性,它说:

x86-64 is fully backwards compatible with 16-bit and 32-bit x86 code.Because the full x86 16-bit and 32-bit instruction sets remain implemented in hardware without any intervening emulation, existing x86 executables run with no compatibility or performance penalties,whereas existing applications that are recoded to take advantage of new features of the processor design may achieve performance improvements.


因此,我已经测试了一些指令,以查看某些指令实际上产生了完全不同的操作码(而不仅仅是应用前缀),例如:INC/DEC。
看着(x86):

\x40 inc eax
\x48 dec eax


并且在x86-x64中组装相同的文件时:

\xff \xc0 inc eax

\xff \xc8 dec eax


我正在尝试找出原因相同的症状并产生不同操作码的其他指令的更多示例。
我对x86-x64中的32位不可用的推,弹出,调用,退出,进入和离开熟悉。

最佳答案

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

删除了说明:

  • 类似于AAM(乘法后调整ASCII)的二进制编码小数,用于在对寄存器进行普通二进制加/sub/mul/div后对固定的二进制编码小数进行固定,每个寄存器中每个4位半部分中都有两个以10为基数的数字。无论如何,它们跑得很慢,没有被使用过。将数字存储为二进制整数而不是BCD是很普遍的。
  • 删除了CS/DS/ES/SS
  • push/pop。 push/pop FS和GS仍然有效(在长模式下,这两个段仍可以具有非零基数)。 mov Sreg, r32mov r32, Sreg仍可用于“已中和”的段寄存器,因此您可以使用暂存整数reg来模拟push/pop。 CS仍然很重要;跳到另一个代码段可以切换到32位模式,而其他代码段仍需要有效的段描述符。
  • 其他晦涩的段内容,例如ARPL:调整段选择器的RPL字段。它实际上只是一个整数寄存器的位域钳位和设置标志指令,因此在少数内核可能需要的地方,可以通过其他一些指令来模拟它。
  • 也许是编译器从未在32位代码中使用的其他一些晦涩或特权的指令。 (并不是说编译器曾经发出过上述任何一种,而没有内在函数或内联汇编代码)。


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

    英特尔的insn引用(遵循the x86 tag wiki或中的链接)显示以下for 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.
    

    N.E.表示不可编码。 Op/En列描述如何对操作数进行编码。

    扬·胡比卡(Jan Hubicka)的AMD64 ISA overview简要描述了REX前缀的单字节inc/dec操作码的用途,默认操作数大小以及即时数据仍为32位的方式。 movabs可用于加载64位立即数,或从64位绝对地址加载/存储。

    AMD's AMD64 manual第2.5.11节重新分配的操作码的表很短。它仅列出:

    变成REX前缀的
  • 4x inc/dec r32
  • 变成63 ARPL
  • MOVSXD(与REX.W = 1(意味着REX前缀中的W位= 1)一起使用时,将dword扩展为qword)。

  • 早期的AMD64和Intel EMT64 CPU在长模式下省略了SAHF/LAHF,但后来用与32位相同的操作码重新添加了该指令。该表也没有列出被完全删除的指令(BCD指令以及其他可能删除的指令),以便为将来的扩展留出空间。

    他们本可以简化很多事情,并使x86-64成为更好的指令集,为将来的扩展留出更多的空间,但是与32bit的每一个区别都意味着更多的解码器晶体管。没有机器指令移至其他64位操作码。

    多个机器指令通常共享相同的asm助记符,mov是最重载的指令。有加载,存储,立即数常量移动,段寄存器移入/移出段寄存器,全都在8位和32位中。 (16位是带有操作数大小前缀的32位,与带有REX前缀的64位相同。)还有一个单独的操作码,用于从64位绝对地址加载RAX。还有一个特殊的操作码,用于将64位立即数加载到寄存器中。 (AT&T语法将其称为movabs,但在Intel/NASM中仍然只是mov)

    关于assembly - x86在x86-x64中不同或已完全删除的32位操作码,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32868293/

    相关文章:

    assembly - x86中的JCC指令是什么

    linux - 为 Linux 调试

    linux - 从 _start 调用 printf 时出现链接器错误

    multithreading - 我们可以使用 x86_64 CPU 原子在 PCI Express 上生成复合原子操作吗?

    c - 为什么 64 位 Ubuntu 中的 8 字节数组 (C) 占用 16 字节?

    assembly - 了解 EIP (RIP) 寄存器如何工作?

    delphi - DUnit2 的 CallerAddr 函数有什么作用?如何将其转换为 64 位?

    linux - __gmon_start 在_start 之前执行

    c - 如何在 gcc/mingw 内联汇编中添加简单的 float4

    x86 - IA-32 上 self IPI 的目的