x86 机器码学习笔记


1 机器码 的结构 {

机器码 有6 个域,分别是:

1. Prefixes (这个域中Prefixes 的顺序可以被打乱)

2. OpCode (是必须的)

3. Byte ModRM

4. Byte SIB

5. Diaplacement

6. imm Operand

其中:

Code 域是必须的,其他域可选。6 个域的顺序绝对不能乱(出现的域,编号小的必须在编号大的之前)。

}

2 一条指令的开始和结束

2.1 开始:CPU 查看EIP,EIP 指向的地址被认为是一条指令的第一个字节。

2.2 结束:CPU 解码机器码(多半是OpCode),计算指令该在哪里结束。如果该指令不是控制类型的指令(改变EIP 的指令),那么指令结束的下一个字节将被认为是下一条指令的开始。

3 Prefixes

性质:

它是唯一在Code 域之前的域,包含一个或多个Prefixes,每一个Prefixes 只有一个byte。如果Prefixes 无法对其后的OpCode 生效,那么该Prefixes 将会被忽略(例如 rep inc eax中,rep 将会被忽略)。

3.1Prefixes 0x66:用于切换默认操作数的大小。默认操作数如果是 32位,那么Prefixes 0x66 将会切换到16 位操作数。所以:在默认操作数是32 位的OS 上,任何操作word 的指令都较操作dword 的指令长一个字节(Prefixes 0x66),并且会多花一个时钟周期去执行。这里的默认操作数由描述符的D/B 位决定:当TYPE 属于 (0x8-0xf] 时段为CS,此时为D 位,代表Default operand size,置位表示默认值是32 位地址(Prefixes 0x67) 和 32 位或8 位操作数(Prefixes 0x66),复位表示默认值是16 位地址 和 16 位或8 位立即数。

3.2 Prefixes 0x67:用于切换默认地址的大小。和Prefixes 0x66 类似。

3.3 Prefixes 0xF2、0xF3:Rep Prefixes。其中0xF2 表示Repne (0 == ecx || 1 == ZF),0xF3 表示Rep/Repe (0 == ecx || 0 == ZF)。如果一条指令对ZF 没有影响,那么0xF3 表示Rep,否则表示Repe。当然对于不改变ZF 的串指令,0xF2 和0xF3 是一样的。

3.4 Prefixes 0x2E、0x3E、0x26、0x36、0x64、0x65 {

这些Prefixes 人称Segment Override Prefixes,用于改变默认段。

其中:

Prefixes对应的段该段的默认指令组
0x2ECSEIP 寄存器
0x3EDS串操作指令的源操作数在DS
0x26ES目的操作数在内存单元的串指令
0x36SS堆栈操作指令
0x64FS
0x65GS

3.5 Prefixes 0xF0 :锁地址总线

PS: 1 Win32 中CS、DS、SS 只是用户模式程序中段的别名,你可以通过上述三个寄存器中阿任意一个来寻址数据。

2 改变目的操作数的值是不允许的,目的操作数无法通过Prefixes 来改变。(例如0x65A5 代表movs [dword es:edi],[dword gs:edi])

}

4 Code 域的种类

x86/x64 平台上,大于1 字节的机器码是通过escape opcode + opcode 形式表示的。

Code 域字节数escape opcode
1
20x0F
3 0x0F3A/0x0F3B
5 ModRM

当有一部分操作数是寄存器或者立即数时,不会用到ModRM寻址,前者直接嵌入到OpCode,后者直接嵌入指令中。

ModRM共有三个部分,格式是2:3:3,三个部分人称ModRM.mod、ModRM.reg、ModRM.r/m。

--
描述
ModRM.mod
b6&b7提供寻址模式
ModRM.regb3-b5指定寄存器
ModRM.r/mb0-b2提供寄存器或内存寻址

5.1 ModRM.mod 提供寻址的模式。这个模式以displacement 值作区别的,当0b11 == ModRM.mod 时,它提供寄存器 寻址。

ModRM.mod
寻址模式
描述
00
[base]
提供 [base] 形式的 memory 寻址
01
[base + disp8]
提供 [base + disp8] 形式的 memory 寻址
10
[base + disp32]
提供 [base + disp32] 形式的 memory 寻址
11
register
提供 register 寻址。
5.2 ModRM.reg reg field 有两种形式,分别对应了全寄存器和局部寄存器

5.2.1 对应8 个全寄存器的情况:

000EAX
001ECX
010EDX
011EBX
100ESP
101EBP
110ESI
111EDI
5.2.2 对应8 个局部寄存器的情况:

000AL
001CL
010DL
011BL
100AH
101CH
110DH
111BH
5.3 ModRM.r/m :最后3 个bit 是r/m,代表register/memory,提供寄存器或者内存寻址。ModRM.r/m 和ModRM.mod 密切相关。

ModRM.mod
ModRM.r/m
ModRM.r/m 寻址
00
000
[eax]
001
[ecx]
010
[edx]
011
[ebx]
100
[SIB]
101
[disp32]
110
[esi]
111
[edi]
01
000
[eax + disp8]
001
[ecx + disp8]
010
[edx + disp8]
011
[ebx + disp8]
100
[SIB + disp8]
101
[ebp + disp8]
110
[esi + disp8]
111
[edi + disp8]
10
000
[eax + disp32]
001
[ecx + disp32]
010
[ebx + disp32]
011
[edx + disp32]
100
[SIB + disp32]
101
[ebp + disp32]
110
[esi + disp32]
111
[edi + disp32]
11
000
eax
001
ecx
010
edx
011
ebx
100
esp
101
ebp
110
esi
111
edi
所以:当ModRM.mod 不是内存寻址模式(0b11 != ModRm.mod)时,如果100 == ModRM.r/m,那么寻址的地址由SIB 补充。

注意:A 当100== ModRM.r/m 时,采用的其实是SIB 寻址,地址由SIB 补充。SIB 中对esp 进行补充寻址有一条重要的规则:esp 不能做index 而只能做base。

B 当101 == ModRM.r/m 时,采用的其实是[disp32] 的寻址。但是在encode 层面,这种情况其实是不存在的。

6 SIB

ModRM 提供的是 registers 寻址、[register] 寻址(寄存器间接寻址)以及 [register + displacement](寄存器基址寻址),SIB 提供的是 [base + index * scale] 这种形式的寻址。即:基址 + 变址。

SIB 的结构和ModRM 类似,同样是2:3:3 结构,分别为SIB.base、SIB.index、SIB.scale。

--
描述
SIB.scale
b6&b7
提供 scale
SIB.index
b3-b5提供 index 寄存器
SIB.base
b0-b2提供 base 寄存器
可以提供[SIB.base + SIB.index*SIB.scale] 形式的寻址。

6.1SIB.scale:可以为 0b00、0b01、0b10、0b11。其中0bnn 代表2^(0bnn),例如SIB.scale 为0b10 便代表4。

6.2 SIB.index:可以用来寻址index 寄存器,寻址模式如下:

SIB.index
寻址模式
000
[eax * 2^(SIB.Scale) + base]
001
[ecx * 2^(SIB.Scale) + base]
010
[edx* 2^(SIB.Scale) + base]
011
[ebx* 2^(SIB.Scale) + base]
100
[base]
101
[ebp* 2^(SIB.Scale) + base]
110
[esi* 2^(SIB.Scale) + base]
111
[edi* 2^(SIB.Scale) + base]

6.3SIB.base:可以用来寻址base 寄存器,寻址模式如下:

ModRM.mod
SIB.base
000
001
010
011
100
101
110
111
00
eax
ecx
edx
ebx
esp
disp32
esi
edi
01
ebp+disp8
10
ebp+disp32
注意:A SIB 的使用必须由ModRM 导出 ,导出的方法为:

SIB 形式ModRM 引出的形式
[SIB]00:xxx:100
[SIB + disp8]01:xxx:100
[SIB + disp32]10:xxx:100

B ModRM 与 SIB 设计上的 2 个原则(上图已经用红色区域标出):

(1)ebp 作为 base 寄存器时,必须以 [ebp + disp] 这种形式存在

(2)esp 不能作为 index 寄存器,可以做为 base 寄存器

7 Displacement


7 指令的多样性
一条相同的指令可以被不同的机器码表示,运行的效果都相同,主要有以下几点原因:

A OpCode 的多样性

B ModRM 寻址能产生和其导出SIB 寻址相同的效果

C displacement 的长度不同,32 位下可以是2 byte 或者8 byte。



  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值