IA32-Mode SMD指令格式
X86指令由:
- 前缀字节prefix (非必需)
- 操作码opcode (必须)
- 内存/寄存器操作数字节ModR/M (非必需)
- 索引寻址描述字节SIB (非必需)
- 常数偏移字节/半字/字Displacement (非必需)
- 立即数字节/半字/字 Immediate (非必需)
- prefix解析
|
种类 |
名称 |
二进制码 |
说明 |
|
LOCK |
LOCK |
F0H |
为了让指令在执行时候先禁用数据线的复用这个特性用在多核的处理器上一般很少需要手动指定 |
|
REP |
REPNE/REPNZ |
F2H |
用CX(16位下)或ECX(32位下)或RCX(64位下)作为指令是否重复执行的依据 |
|
REP/REPE/REPZ |
F3H |
同上 |
|
|
Segment Override |
CS |
2EH |
段重载(默认数据移动指令使用DS段) |
|
SS |
36H |
同上 |
|
|
DS |
3EH |
同上 |
|
|
ES |
26H |
同上 |
|
|
FS |
64H |
同上 |
|
|
GS |
65H |
同上 |
|
|
Oprandsize Override |
Oprandsize Override |
66H |
访问32位和16位寄存器用这个前缀来区别 |
|
Address Override |
Address Override |
67H |
64位下指定用64位还是32位寄存器作为索引 |
2. ModR/M 解析
由上面的指令格式已知Mod/RM域分为3个部分:
- Mod (两个位)
- Reg/Opcode (三个位)
- R/M (三个位)
2.1 Mod
以上左图是16位下的modr/m解析,右图是32位下modr/m解析
Mod由两个位组成,来指定寻址方式,分别是
2.2 R/M
- 寄存器寻址
- 寄存器加偏移寻址(8位)
- 寄存器加偏移寻址(16/32位)
- 寄存器操作数(只操作寄存器而非内存)
Mod是两位的数据所以可以指定4种寻址方式,而每一种方式里面还对应着不同的选择,这些不同的选择由R/M来决定,这个域由3个位组成,也就是说有8种方式来选择,由上面的图可以对应从000B到111B的所有编码对应的选择.
2.3 REG/OPCODE
这个域由不同的opcode来决定功能到底是opcode的补充还是作为oprand的编码.
16/32位的编码如下
3. SIB解析
在modr/m解析中红色圈出来的和其他不同,原因是当mod≠11(也就是访问内存操作而不是寄存器操作)的时候,当R/M=100B的时候,说明要使用”索引寻址”,这个时候,指令的编码就会使用SIB字节,这个字节由3部分组成,分别是Scale Index Base.
举例来说,一条mov指令如下:
mov ptr [ebx + eax * 4], ecx
这条mov把ecx寄存器中的内容mov到 ebx + eax * 4 的内存地址中,这样的地址,就是索引寻址,也就是说会使用SIB字节,而其中
- ebx 是 Base
- eax 是 Index
- scale值是4
这张表是32位下SIB的编码方式 (16位模式不支持这种寻址方式)
3.1 Scale
类似于Mod,两个位组成,来选择index到底要乘以几来组成最后的寻址地址,可选项是1 2 4 8,四种选择.
3.2 Index
类似于R/M来指定到底是那个寄存器一样,index这个域来指定到底是用哪个寄存器作为index
3.3 Base
来指定基地址,需要注意的是在汇编中,这个base可以省略,那么实际上在指令的编码中一定有对应项说明base是被省略的---就是base=101B的时候.
25 asm(
26 "movw %%ax, %%bx; \
27 movb %%bh, %%ch; \
28 movl (%%eax, %%eax, 4), %%ebx; \
29 movq (%%rax, %%rbx, 4), %%rbx; \
30 movl (, %%eax, 4), %%ebx; \
31 movq (, %%rax, 4), %%rbx"
32 : \
33 : \
34 );
上面的这部分嵌入式汇编代码,编译生成二进制之后我再反汇编出结果对比如下:
400689: 66 89 c3 mov %ax,%bx
40068c: 88 fd mov %bh,%ch
40068e: 67 8b 1c 80 mov (%eax,%eax,4),%ebx
400692: 48 8b 1c 98 mov (%rax,%rbx,4),%rbx
400696: 67 8b 1c 85 00 00 00 mov 0x0(,%eax,4),%ebx
两条代码的比对,可发现上面的规则,也就是没有指定base的时候会引入一个立即数作为偏移,但是如果指令没有指定立即数则汇编器就把立即数写成0.
4. Displacement
偏移数,1 2 或 4 个字节, 按照小端排列.
例: 48 8b 1c 85 cd ab 00 mov 0xabcd(,%rax,4),%rbx
5. Immediate
立即数,1 2 或 4 个字节, 按照小端排列
举例说明:
以上就是IA32 Mode下指令的编码,64Bit Mode的编码文章链接https://blog.csdn.net/ross1206/article/details/81663614