【问题标题】:x64 instruction encoding (r/m, reg vs reg, r/m)x64 指令编码 (r/m, reg vs reg, r/m)
【发布时间】:2015-04-23 01:06:42
【问题描述】:

编码 (ModRM:r/m, ModRM:reg) 与 (ModRM:reg, ModRM:r/m) 有什么区别?具体来说说像 CMPXCHG 与 DIVPD 这样的指令。我认为寄存器和地址总是在第一个字节中编码,然后如果需要,第二个字节中的 SIB 和位移?这是我的代码:

    static void WriteRegisterToMemory(ICollection<Byte> bytes, IRegisterToMemoryInstruction instruction, Byte rex)
    {
        IAddress address = instruction.Address;
        Byte register = instruction.Register;

        if (address.NeedsRex)
        {
            rex |= 0x40;
            if (address.RexB)
                rex |= 1;
            if (address.RexX)
                rex |= 1 << 1;
        }

        if (register > 7)
            rex |= 0x44;        // REX.R
        if (rex != 0)
            bytes.Add(rex);

        bytes.AddRange(instruction.Opcode);
        Byte modRM = (Byte)((register % 8) << 3);
        modRM |= address.GetModRMAddressByte();
        bytes.Add(modRM);
        address.WriteScaledIndexByteAndDisplacement(bytes);
    }

所以这两条指令的编码完全相同,只是操作码不同? (英特尔 x64 手册第 457 页上的添加)

Op/En Operand 1        Operand 2 
RM    ModRM:reg (r, w) ModRM:r/m (r) 
MR    ModRM:r/m (r, w) ModRM:reg (r)

【问题讨论】:

    标签: 64-bit machine-code


    【解决方案1】:

    w.r.t 并没有什么不同。编码,区别在于哪个是源,哪个是目的地。大多数指令都以r/m 作为源,除了cmpxchgbtsxaddxchg 这样的指令模棱两可(它是对称的),ALU 操作有一个r/m, r 形式和一个r/m, imm形式,显然是 mov 的记忆。因此,在对这些指令进行编码时(即使两个操作数都是寄存器),请注意它们的“左右方向”,否则它们最终可能会交换操作数。但仅此而已,最终它们的编码方式没有区别。

    【讨论】:

    • 编辑帖子问另一个问题
    • @RyanBrown 好的,我真的不明白你想知道什么,在这种情况下,“编码相同”是什么意思?无论如何,add [eax], edxadd edx, [eax](假设为 32 位)之间的唯一区别是操作码,它们都有一个 ModRM 字节 10
    • 我只是不明白为什么他们同时拥有(reg 然后 r/m)和(r/m 然后 reg)。它们都编码为一个字节(通常),所以它们并不是真正的两个单独的操作数......
    • @RyanBrown 但语义不一样,ModR/M 没有“操作数顺序”,但指令确实有“r 是目标还是r/m 目的地"
    猜你喜欢
    • 2012-01-15
    • 2015-02-13
    • 1970-01-01
    • 2016-02-16
    • 1970-01-01
    • 1970-01-01
    • 2020-06-06
    • 2021-02-15
    相关资源
    最近更新 更多