GAS为以下说明提供了以下编码:

push rbp    # 0x55
push rbx    # 0x53
push r12    # 0x41 0x54
push r13    # 0x41 0x55

AMD64 spec(页313):



由于rbprbx的偏移量分别为5和3,因此前两种编码是有意义的。我不明白最后两种编码的情况。

我知道0x40-0x4f是REX前缀,并且0x41设置了REX.B位(根据此external reference,它是MODRM.rmSIB.base的MSB的扩展)。该规范提到要访问所有16个GPR,您都需要使用REX,但不清楚截止位置。

从咨询MODRM和SIB的文档开始,我不认为会使用SIB,因为它的目的是使用基址+偏移量寄存器进行索引(尽管老实说,我不能真正告诉您如何区分MODRM和SIB只是因为编码)。

因此,我怀疑在这里使用了MODRM。目前仅考虑push r12(0x41 0x54)(并注意r12具有偏移量12),我们有:
+----------------+--------------------+
| 0x41           | 0x54               |
+----------------+--------------------+
| REX            | MODRM              |
+--------+-------+-----+--------+-----+
| Prefix | WRXB  | mod | reg    | rm  |
| 0100   | 0001  | 01  | 01   0 | 100 |
+--------+-------+-----+--------+-----+
REX.B + MODRM.rm = 0b1100 = 12,因此这将表明它是源寄存器(r12 =偏移量12)。如果您忽略external (unofficial) reference中的所有表REX.R + MODRM.mod + MODRM.reg = 0b00101 = 5,这是推送指令库0x50的第一个半字节。

所以,我想我已经把它弄倒了,但是我不明白如何得到像0x41 0x54这样的编码。在AMD reference中,图1-10(第54页)有一个脚注,如果为MODRM.mod = 01 or 10,则字节“包括由指令置换字段指定的偏移量”。这也许暗示了我们为什么要偏移指令REX.R + MODRM.mod + MODRM.reg = 0b00101 = 5。但是,为什么MODRM.mod是指令偏移量的一部分呢?如果必须包含它,则采用此偏移量格式的指令仅限于前缀0b010x10。那是不对的,对不对?

tl; dr
  • REX编码实际上如何用于push之类的指令?
  • 需要REX前缀的指令偏移量截止值是多少? (是否已证明我无法像push r12push rbp那样为push rbx做0x50 + 12?)
  • 为什么在指令库的前缀中包含MODRM.mod? (或者这完全正确吗?)
  • 这对于类似pop的类似指令是否一致? (而且我怎么知道哪些指令支持此功能?它对所有操作码形式为XX +xx的指令都起作用吗?)
  • 官方手册在哪里记录了此内容?
  • 如何区分REX前缀后面是MODRM字节还是SIB字节?
  • 是否有更好的文档,也许可以分步地安排这些过程,而不是使您在表之间的几页之间跳转?
  • 最佳答案

    显然这里没有ModRM字节,因为整个指令是一个字节。没有操作码字节,就无法拥有ModRM。
    push reg/pop reg简短形式将 3位寄存器代码嵌入到操作码字节中。这就是50 + rq的意思。 (与确实使用ModRM的 FF /6 push r/m64 编码不同;您可以使用该编码对寄存器操作数进行编码,以使指令更长,但通常只将其用于push qword [rdi]或其他内容)。

    与16/32位相同,这就是为什么x86-64需要一个额外的位(来自REX前缀)来编码其中一个具有4位代码且前导位已设置的"new"/高位寄存器之一的原因。

    OSdev省略了这种情况,只提到了ModRM.rmSIB.base

    英特尔第2卷手册PDF记录了以下编码:



    毫无疑问,表3-1使用与ModRM和SIB中的寄存器编号相同的编码方案,但是Intel竭尽全力,并针对所有操作数大小,提供了所有整数寄存器的完整表。包括AH/BH/CH/DH,因为mov ah, 1可以使用2字节的短格式。

    我从“四字寄存器(仅64位模式)”列中摘录了相关的行:

    From Intel's Table 3-1. Register Codes Associated With +rb, +rw, +rd, +ro
            reg    REX.B  Reg Field
            RBX    None    3
    
            RBP    None    5
    
            R12    Yes     4
            R13    Yes     5
    

    有趣的事实:在Intel手册中,他们实际上使用50 + rd而不是50 + ro来表示PUSH r64,与在32位模式下使用push r32一样。 https://www.felixcloutier.com/x86/push



    是的。 push/pop regmov reg,immxchg eax, r32/xchg rax, r64都使用具有3个操作码位的相同编码来对寄存器进行编码。

    如果我们可以将这8个xchg操作码返回来获得更有用的功能(例如在64位模式下更紧凑的VEX或EVEX前缀),那将是很好的选择,但是当AMD与AMD64一起保守地使用它时,它就大行其道,主要是使机器代码保持相似尽可能到32位模式。但是,他们确实收回了0x4? inc/dec reg操作码以用作REX前缀。

    关于assembly - PUSH的英特尔REX编码,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/54519462/

    10-12 18:30