如何阅读英特尔操作码表示法

时间:2013-02-22 05:43:49

标签: assembly x86 intel opcode machine-code

我正在阅读一些关于英特尔操作码汇编指令的资料,但我无法理解它遵循操作码字节是什么意思。例如:“cw”,“cd”,“/ 2”,“cp”,“/ 3”。 请给我一个提示是什么意思或在哪里可以找到完整的参考?提前谢谢!

E8 cw CALL rel16相对于下一条指令调用近,相对位移

E8 cd CALL rel32相对于下一条指令调用near,relative,displacement

FF / 2 CALL r / m16呼叫接近,绝对间接,r / m16中给出的地址

FF / 2 CALL r / m32呼叫接近,绝对间接,r / m32中给出的地址

9A cd CALL ptr16:16调用操作数中给出的far,absolute,address

9A cp CALL ptr16:32调用操作数中给出的far,absolute,address

FF / 3 CALL m16:16调用远,绝对间接,m16:16中给出的地址

FF / 3 CALL m16:32调用远,绝对间接,m16:32中给出的地址

2 个答案:

答案 0 :(得分:11)

我最喜欢的来源是英特尔本身:Intel® 64 and IA-32 Architectures Software Developer Manuals。与过去的版本不同,所有卷现在都很好地包含在一个(3044页)PDF中。

看起来最有帮助的部分是第2卷第3章中的3.1.1.1(截至我写这篇文章的最新PDF版本的第432页)。

答案 1 :(得分:2)

许多用于指令即时版本的操作码,包括83,使用ModR / M字节中的3位/r字段作为3个额外的操作码位。英特尔的第2卷手册对此进行了说明,我认为附录中的操作码表中包括了它。

这就是为什么大多数原始8086立即指令(如and r/m, imm仍只允许2个操作数,而与shrd eax, edx, 4imul edx, [rdi], 12345不同的是,两个ModRM字段均用于编码dst / src操作数,以及表示立即操作数的操作码。

SHRD / SHLD并添加了386,imul-immediate添加了286。不幸的是,复制与(and eax, edx, 0xf)无法编码,但是至少x86可以将LEA用于非常常见的复制和添加或子操作。

但是,如果每条立即数和单操作数指令(如pushnot)本身都需要完整的操作码,则8086将用1字节的操作码。 (特别是因为设计人员选择在简短形式上花费大量编码空间,而AL和AX没有现代字节,例如cmp ax, 12345仅是3个字节,而不是16位模式下的4个字节,或者cmp eax, imm32在32位模式下cmp r/m32, imm32只有5个字节,而不是6个字节。对于单字节xchg-with-ax和一个字节的inc / dec寄存器。)


示例:解码48 83 C4 38(摘自How does one opcode byte decode to different instructions depending on the "register/opcode" field? What is that?,此Q的副本)

48是REX.W前缀(REX仅设置了W位,因此它指示64位操作数的大小,但没有高位寄存器)。

操作码83表示它可以是7种不同的指令,具体取决于称为“寄存器/操作码字段”的字段

每条指令的文档,例如add (html extract of the vol2 manual),显示类似
的编码 REX.W + 83 /0 ib代表ADD r/m64, imm8,这就是您所拥有的。

  

diagram of the ModRM bit fields from wiki.osdev.org

  7                           0
+---+---+---+---+---+---+---+---+
|  mod  |    reg    |     rm    |
+---+---+---+---+---+---+---+---+

0xc4 = 0b11000100,因此reg字段=0。因此,我们的操作码为83 /0,以Intel的符号表示。

其余的ModRM字段为:

  • mode = 0b11,因此rm字段编码的是寄存器操作数,而不是寻址模式的基址寄存器。
  • rm = 0b100。规则#4 = SPL / SP / ESP / RSP。 (在本例中为RSP,因为它是64位操作数大小)。有关表格,请参阅英特尔手册,或https://wiki.osdev.org/X86-64_Instruction_Encoding#Registers

所以指令是add rsp, 0x38

ndisasm -b64同意:

$ cat > foo.asm
db 0x48, 0x83, 0xC4, 0x38
$ nasm foo.asm     # create a flat binary with those bytes, not an object file
$ ndisasm -b64 foo
00000000  4883C438          add rsp,byte +0x38