引言
看了两天的x86指令集,终于基本搞懂了x64的指令格式(只是x64哦,没有特别关注16位和32位时的格式),和RISC相比实在是太复杂了,难怪x86的功耗将不下来,光是译码器就不知道得做的多么复杂。
x64指令格式
x64指令共包括七个部分,即:
- legacy prefix(一个字节)
- REX prefix(一个字节)
- opcode(一到三个字节)
- ModRM(一个字节)
- SIB(一个字节)
- disp(最多可以8个字节)
- imm(最多可以8个字节)
legacy prefix
legacy prefix在x64下应该不常用。一种情况是需要使用16位的operand时(例如mov ax 0x1234
),需加前缀0x66以改变default operand size
(x64下该值是32)。还有就是需要lock的情况。还有其他情况就没有细看了。
REX
REX前缀非常重要,正是这个前缀将x86带入了64位模式。它的高四位一定是0x4,低四位分别代表W、R、X、B。
- W:x64模式下大部分指令的
default operand size
是32位的,对这类指令,如果需要64位的操作数,将需要将W置位,例如mov rax rbx
。 - R:将
ModRM.reg
从8个扩展到16个。 - X:将
SIB.index
寄存器从8个扩展到16个 - B:将
SIB.base
或者ModRM.r/m
或者Opcode.reg
寄存器从8个扩展到16个。所以能有如上的或
关系,是因为当SIB.base
表示base寄存器时,ModRM.r/m
必为100以作为SIB域的存在标记,而不再表示一个寄存器。
Opcode
Opcode的长度可以从一个字节到三个字节不等。一个字节时有时需要配合ModRM.reg
才能明确具体功能。我们在指令手册中看到opcode /d
的情况这个/d
就是指的ModRM.reg
的值。另外opcode两个字节时第一个字节一定是0x0F
作为引导。
ModRM
ModeRM字段又2-3-3的依次分成mode
、reg
和r/m
三个域。
reg
域通常作为指令的dest寄存器,或者作为某些opcode的补充。
mode=11
时表示寄存器直接寻址,寄存器由r/m
域指定,例如r/m=000
就表示直接取rax
寄存器的值。
mode=00
表示寄存器间接寻址,寄存器由r/m
域指定,即[r/m]
,但有两种特殊情况:
r/m=100
不表示[rsp]
,而是作为SIB字段的存在标志r/m=101
不表示[rbp]
,而是表示仅包含立即数的间接寻址,即[disp32]
mode=01
通常表示[r/m+disp8]
,但
- 如果
r/m=100
,则表示[base+index*scalar+disp8]
- 如果
r/m=101
,则表示[rbp+disp8]
mode=10
表示[r/m+disp32]
- 如果
r/m=100
,则表示[base+index*scalar+disp32]
- 如果
r/m=101
,则表示[rbp+disp32]
最后,针对rsp,如果的确需要[rsp]
,补救的措施是当r/m=100
时,将SIB的index域也置为100,并令此时表示[base]
,这样令base=100
,就表示[rsp]了
。总结一下:
mode=00, r/m=100, index=100, base=100
表示[rsp]
mode=01, r/m=100, index=100, base=100
表示[rsp+disp8]
mode=10, r/m=100, index=100, base=100
表示[rsp+disp32]
最最后,x64不支持[rbp]
,如果非要[rbp]
,只能用[rbp+0x00]
编码
SIB
SIB字段2-3-3的依次分为scalar、index和base三个域。
scalar取00表示乘1, 取01表示乘2, 取10表示乘4, 取11表示乘8.
index用于指示8个寄存器,结合REX.X位指示16个寄存器。
base用于指示8个寄存器,结合REX.B位指示16个寄存器。
如何参考Intel指令手册
字(word)是16位,32位称为双字,64位称为四字。
Intel格式汇编如果有两个操作数,通常dest在左,src在右,如mov dest src
REX.W:指示operand size的变化
/digit:指示ModRM中与opcode结合以确定实际操作的reg域的值
/r:指示ModRM字段中的reg域表示dest寄存器
cb, cw, cd, cp, co, ct:A 1-byte (cb), 2-byte (cw), 4-byte (cd), 6-byte (cp), 8-byte (co) or 10-byte (ct) value following the opcode.
ib, iw, id, io:A 1-byte (ib), 2-byte (iw), 4-byte (id) or 8-byte (io) immediate operand to the instruction that follows the opcode, ModR/M bytes or SIB bytes.
+rb, +rw, +rd, +ro:没看懂!!
r/m32: A doubleword general-purpose register or memory operand used for instructions whose operand-size attribute is 32 bits.
r/m64:A quadword general-purpose register or memory operand used for instructions whose operand-size attribute is 64 bits when using REX.W.
参考文献
- Intel® 64 and IA-32 Architectures Software Developer’s Manual,Volume 2A:Instruction Set Reference, A-M
- http://www.mouseos.com/x64/index.html