x64 指令编码(r/m,reg 与 reg,r/m)
x64 instruction encoding (r/m, reg vs reg, r/m)
编码 (ModRM:r/m, ModRM:reg) 与 (ModRM:reg, ModRM:r/m) 有什么区别?具体说像 CMPXCHG vs 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);
}
所以这两条指令的编码完全相同,只是操作码不同? (在 intel 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)
确实没有什么区别w.r.t。编码,区别在于哪个是源,哪个是目的地。大多数指令都以 r/m
作为源,除了像 cmpxchg
、bts
、xadd
、xchg
之类的东西是模棱两可的(它是对称的),ALU ops 有一个 r/m, r
形式和一个 r/m, imm
形式,显然是 mov 到记忆中。因此,在对这些指令进行编码时(即使两个操作数都是寄存器),也要小心 "which way around" 它们是,否则它们最终可能会交换操作数。不过也仅此而已,最终编码方式没有什么区别
编码 (ModRM:r/m, ModRM:reg) 与 (ModRM:reg, ModRM:r/m) 有什么区别?具体说像 CMPXCHG vs 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);
}
所以这两条指令的编码完全相同,只是操作码不同? (在 intel 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)
确实没有什么区别w.r.t。编码,区别在于哪个是源,哪个是目的地。大多数指令都以 r/m
作为源,除了像 cmpxchg
、bts
、xadd
、xchg
之类的东西是模棱两可的(它是对称的),ALU ops 有一个 r/m, r
形式和一个 r/m, imm
形式,显然是 mov 到记忆中。因此,在对这些指令进行编码时(即使两个操作数都是寄存器),也要小心 "which way around" 它们是,否则它们最终可能会交换操作数。不过也仅此而已,最终编码方式没有什么区别