目录
- x64汇编第二讲,复习x86汇编指令格式,学习x64指令格式
- 一丶x86指令复习.
- 1.1什么是x86指令.
- 1.2 x86与x64下的通用寄存器
- 1.3 OpCode
- 1.4 7种寻址方式
- 二丶x86指令格式详解.
- 2.1 instruction 说明
- 2.2 Opcode
- 2.3 ModR/m说明
- 2.4 SIB说明
- 2.5 Displacement 偏移说明
- 2.6 immediate 立即数
- 二丶X64 汇编指令格式详解
- 一丶x86指令复习.
x64汇编第二讲,复习x86汇编指令格式,学习x64指令格式
一丶x86指令复习.
1.1什么是x86指令.
代码如下.
高级代码为:
代码语言:javascript复制int i = 0;
int *p - &i;
此时产生了3条汇编指令
代码语言:javascript复制mov dword ptr[i],0 OPCODE = C7 45 F4 00 00 00 00
lea eax,[i]
mov dword ptr [p],ea OPCODE = 89 45 E8
此时观察,有两条 Mov指令. 但是机器码却不同.这个就是我们今天要讲的.
1.2 x86与x64下的通用寄存器
在x86下面,我们的通用寄存器有
代码语言:javascript复制eax ebx ecx edx esi edi esp ebp [e 代表 Extend(扩展)]
在x64下面,新加了几个寄存器.并且指令变大了 有16个通用寄存器
代码语言:javascript复制rax rbx rcx rdx rsi rdi rsp rbp
r8 r9 r10 r11 r12 r13 r14 15
在x86下,我们的寄存器都有自己的编号.
指令 | 编号 |
---|---|
eax | 000 |
ecx | 001 |
edx | 010 |
ebx | 011 |
esp | 100 |
ebp | 101 |
esi | 110 |
edi | 111 |
1.3 OpCode
每个指令都有一个或者多个编码. 如下常见的
指令 | OpCode | 说明 |
---|---|---|
ret | 0xC3 | 返回 |
short jump | 0xEB | 短跳转 8位 |
far jump | 0xEA | 长跳转,可以在4GB空间任意跳转 32位 |
je/jz | 0x74 | 判断是否相等 |
jne/jnz | 0x75 | 判断是否不等 |
nop | 0x90 | 空指令 |
1.4 7种寻址方式
寻址方式 | 寻址代码 |
---|---|
立即数寻址 | mov eax,1 |
寄存器寻址 | mov eax,ebx |
直接寻址 | mov eax,[2000h] |
寄存器间接寻址 | mov eax,[ebx] |
寄存器相对寻址 | mov eax[ebx 0x100] |
基址变址寻址 | mov eax,[ebx esi] |
相对基址变址寻址 | mov eax,[ebx esi *n] |
二丶x86指令格式详解.
在X86下,查看inter手册可以清楚的看到x86汇编的指令格式. 图标如下
x64的图表
以x86为例,有6个部分. 只有Opcode时必须的.前边的可以没有
2.1 instruction 说明
instruction prefixes 指令前缀. 如 rep movs bytes ptr[esi] rep 就是前缀.
2.2 Opcode
Opcode 这个需要查看inter手册. 如下:
2.3 ModR/m说明
ModR/m 里面分为三部分
指令 | 说明 |
---|---|
Mod | 表示寄存器的寻址方式. |
Reg/opcode | 表示寄存器或者OpCode的编码 |
R/M | 表示汇编中第一个寄存器的编码. |
Mod 代表寻址方式 2位表示
指令 | 说明 |
---|---|
00 | 寄存器间接寻址 |
01 | 寄存器相对寻址偏移 |
10 | 寄存器先对寻址偏移 |
11 | 寄存器直接寻址 |
其它寻址方式放在SIB里面
Reg/Opcode 代表指令, 如 mov [ebp - 38h],eax. 那么就代表eax的编号 有时候表示寄存器,有时候表示Opcode
R/M 表示汇编的第一个寄存器 如 mov[ebp - 38h],eax 代表的是ebp
2.4 SIB说明
SIB 占一个字节.可能有可能没有,是对ModR/M寻址的补充.
一条汇编指令
代码语言:javascript复制mov eax,[ebx edi * 4 1000h]
根据汇编指令我们可以得出: 偏移 = 1000h 倍率 = 4 基址 = ebx
那么根据上面我们的SIB解析就好办了
名称 | 大小 | 说明 |
---|---|---|
scale | 2 bit | 表示倍率,如上面edi *4 4就是倍率,只能是1 2 4 8 ,00代表倍率为1,01=2 10 = 4 11 = 8 |
index | 3 bit | 表示倍率前边的寄存器 如edx * 4,那么edi的编号就放在这里 |
base | 3 bit |
那么根木上面说明我们可以拆分如下.
scale | index | base |
---|---|---|
4 | edi | ebx |
2.5 Displacement 偏移说明
Displacement 其实是一个偏移 如:
代码语言:javascript复制mov eax,[ebx edi * 4 1000h]
1000h就是偏移,会放在这个字段当中.
可以是1个字节,可以是2个字节,或者4个字节.
2.6 immediate 立即数
immediate 是立即数 如:
代码语言:javascript复制mov eax,1
在32位中占 1 2 4个字节.
其中讲到这大概说明白了. 除了Opcode不能省略.其余都是可选的. 在32位指令最长可以支持17个字节.
二丶X64 汇编指令格式详解
x86图表
x64的图表
在x64下,只对 x86加了一个 REX (re Extend 在扩展)
REX是一个字节.但是高4位必须为0100 REX取值范围在40-4F之间.
低四位有不同的含义,这是inter手册拿下来的
W (width) 如果为0 代表这个指令是32位的 如果为1 则代表指令是64位的.
R位
R主要是对32位下 MOdR/M中的 Reg/Opcode做了扩充. 以前是3位,现在是4位来表示了. 因为为了兼容32位.所以32位的表不能动.所以只能在这继续进行扩充.
X(index} 这个主要是扩充 SIB 中的index位的.
32位下 Index代表 倍率的寄存器.如 edi * 4 4是倍率. edi则是 倍率寄存器.在32位下这个是3位.只能表示一个寄存器 64下需要对它进行扩种.就是x index.
B(base)
这个主要是扩充 32位下 Modr/M 中的 R/M位. 或者 SIB中 Base基址位.
例子: 如:
代码语言:javascript复制mov eax,2
Opcode = b8 10 0 00 00
那么扩展为64位的就是 48 b8 10 00 00 00 00 00 00 00
48的意思就是 0100 1000 就是说 在w 位设置为1,代表的是64位汇编指令.