一. IA-32指令格式
1. 知识补充(JCC)
| JCC | 意义 | 标志位 |
|---|---|---|
| JE、JZ | 结果为零则跳转(相等时跳转) | ZF=1 |
| JNE、JNZ | 结果不为零则跳转(不相等时跳转) | ZF=0 |
| JS | 结果为负则跳转 | SF=1 |
| JNS | 结果为非负则跳转 | SF=0 |
| JP、JPE | 结果中1的个数为偶数则跳转 | PF=1 |
| JNP、JPO | 结果中1的个数为偶数则跳转 | PF=0 |
| JO | 结果溢出了则跳转 | OF=1 |
| JNO | 结果没有溢出则跳转 | OF=0 |
| JB、JNAE、JC | 小于则跳转 (无符号数) | CF=1 |
| JNB、JAE、JNC | 大于等于则跳转 (无符号数) | CF=0 |
| JBE、JNA | 小于等于则跳转 (无符号数) | CF=1 or ZF=1 |
| JBNE、JA | 大于则跳转(无符号数) | CF=0 and ZF=0 |
| JL、JNGE | 小于则跳转 (有符号数) | SF≠OF |
| JNL、JGE | 大于等于则跳转 (有符号数) | SF=OF |
| JLE、JNG | 小于等于则跳转 (有符号数) | ZF=1 or SF≠OF |
| JNLE、JG | 大于则跳转(有符号数) | ZF=0 and SF=OF |
2. 指令格式

寄存器编号:

3. intel手册缩写表
详见Intel® 64 and IA-32 Architectures Software Developer’s Manual, Volume 2 APPENDIX A OPCODE MAP, KEY TO ABBREVIATIONS
(1) 寻址方法代码
| 缩写 | 意义 |
|---|---|
| E | 在opcode后面有一个字节的ModR/M, ModR/M制定了操作数的类型. 操作数是通用寄存器或者内存地址 |
| F | EFLAGS/RFLAGS Register. |
| G | ModR/M的reg字段选择的一个通用寄存器 |
| I | 立即数, 该操作数的值被直接编码到了指令的后续字节中 |
| J | 用来修改EIP的相对偏移量 |
(2) 操作数类型代码
| 缩写 | 意义 |
|---|---|
| b | 字节, 不管操作数大小属性 |
| c | 字节或字,取决于操作数大小属性 |
| d | 四字节, 不管操作数大小属性 |
| v | 字、双字或四字(在64位模式下), 取决于操作数大小属性 |
| w | 两个字节,不考虑操作数大小属性 |
二. 经典定长指令
1. 0x50-0x57
指令长度: 1字节
| 硬编码 | 汇编 |
|---|---|
| 0x50 | PUSH EAX |
| 0x51 | PUSH ECX |
| 0x52 | PUSH EDX |
| 0x53 | PUSH EBX |
| 0x54 | PUSH ESP |
| 0x55 | PUSH EBP |
| 0x56 | PUSH ESI |
| 0x57 | PUSH EDI |
2. 0x58-0x5F
指令长度: 1字节
| 硬编码 | 汇编 |
|---|---|
| 0x58 | POP EAX |
| 0x59 | POP ECX |
| 0x5A | POP EDX |
| 0x5B | POP EBX |
| 0x5C | POP ESP |
| 0x5D | POP EBP |
| 0x5E | POP ESI |
| 0x5F | POP EDI |
3. 0x60-0x61
指令长度: 1字节
| 硬编码 | 汇编 |
|---|---|
| 0x60 | PUSHAD |
| 0x61 | PUSHFD |
4. 0x40-0x47
指令长度: 1字节
| 硬编码 | 汇编 |
|---|---|
| 0x40 | INC EAX |
| 0x41 | INC ECX |
| 0x42 | INC EDX |
| 0x43 | INC EBX |
| 0x44 | INC ESP |
| 0x45 | INC EBP |
| 0x46 | INC ESI |
| 0x47 | INC EDI |
5. 0x48-0x4F
指令长度: 1字节
| 硬编码 | 汇编 |
|---|---|
| 0x48 | DEC EAX |
| 0x49 | DEC ECX |
| 0x4A | DEC EDX |
| 0x4B | DEC EBX |
| 0x4C | DEC ESP |
| 0x4D | DEC EBP |
| 0x4E | DEC ESI |
| 0x4F | DEC EDI |
6. 0xB0-0xB7
指令长度: 2字节
| 硬编码 | 汇编 |
|---|---|
| 0xB0 | MOV AL, Ib |
| 0xB1 | MOV CL, Ib |
| 0xB2 | MOV DL, Ib |
| 0xB3 | MOV BL, Ib |
| 0xB4 | MOV AH, Ib |
| 0xB5 | MOV CH, Ib |
| 0xB6 | MOV DH, Ib |
| 0xB7 | MOV BH, Ib |
7. 0xB8-0xBF
指令长度: 5字节
| 硬编码 | 汇编 |
|---|---|
| 0xB8 | MOV EAX, Id |
| 0xB9 | MOV ECX, Id |
| 0xBA | MOV EDX, Id |
| 0xBB | MOV EBX, Id |
| 0xBC | MOV ESP, Id |
| 0xBD | MOV EBP, Id |
| 0xBE | MOV ESI, Id |
| 0xBF | MOV EDI, Id |
8. 0x90-0x97
指令长度: 1字节
| 硬编码 | 汇编 |
|---|---|
| 0x90 | NOP(XCHG EAX, EAX) |
| 0x91 | XCHG EAX, ECX |
| 0x92 | XCHG EAX, EDX |
| 0x93 | XCHG EAX, EBX |
| 0x94 | XCHG EAX, ESP |
| 0x95 | XCHG EAX, EBP |
| 0x96 | XCHG EAX, ESI |
| 0x97 | XCHG EAX, EDI |
Intel在设计的时候会对0号寄存器照顾,也就是0号寄存器会有单独的指令,对于XCHG EBX, EDX就没有一个字节的指令了
注意: XCHG ECX, EAX和XCHG EAX, ECX硬编码相同,其余同理,但是XCHG EBX, ECX和XCHG ECX, EBX硬编码不同
9. 0x70-0x7F
指令长度: 2字节
条件跳转,后跟一个字节立即数的偏移(有符号数)
jcc Jb
Jb = 要跳转的地址 - 下一条指令的地址 = 要跳转的地址 - (当前指令地址 + 当前指令长度)
如果条件成立,跳转到当前指令地址 + 当前指令长度 + Jb
最大向前跳0x7F,向后跳0x80
| 硬编码 | 汇编 |
|---|---|
| 0x70 | JO |
| 0x71 | JNO |
| 0x72 | JB/JNAE/JC |
| 0x73 | JNB/JAE/JNC |
| 0x74 | JZ/JE |
| 0x75 | JNZ/JNE |
| 0x76 | JBE/JNA |
| 0x77 | JNBE/JA |
| 0x78 | JS |
| 0x79 | JNS |
| 0x7A | JP/JPE |
| 0x7B | JNP/JPO |
| 0x7C | JL/JNGE |
| 0x7D | JNL/JGE |
| 0x7E | JLE/JNG |
| 0x7F | JNLE/JG |
10. 0x0F 0x80 - 0x0F 0x8F
指令长度: 六个字节
条件跳转,后跟四个字节立即数的偏移(有符号数)
jcc Jd
Jd = 要跳转的地址 - 下一条指令的地址 = 要跳转的地址 - (当前指令地址 + 当前指令长度)
如果条件成立,跳转到当前指令地址 + 当前指令长度 + Jd
最大向前跳0x7FFFFFFF,向后跳0x80000000
| 硬编码 | 汇编 |
|---|---|
| 0x0F 0x80 | JO |
| 0x0F 0x81 | JNO |
| 0x0F 0x82 | JB/JNAE/JC |
| 0x0F 0x83 | JNB/JAE/JNC |
| 0x0F 0x84 | JZ/JE |
| 0x0F 0x85 | JNZ/JNE |
| 0x0F 0x86 | JBE/JNA |
| 0x0F 0x87 | JNBE/JA |
| 0x0F 0x88 | JS |
| 0x0F 0x89 | JNS |
| 0x0F 0x8A | JP/JPE |
| 0x0F 0x8B | JNP/JPO |
| 0x0F 0x8C | JL/JNGE |
| 0x0F 0x8D | JNL/JGE |
| 0x0F 0x8E | JLE/JNG |
| 0x0F 0x8F | JNLE/JG |
11. 其他指令
(1) 0xE0
LOOPNE/LOOPNZ Jb
指令长度: 两个字节
ECX = ECX - 1
当ZF = 0 && ECX!=0 时跳转到当前指令地址 + 当前指令长度 + Jb
(2) 0xE1
LOOPE/LOOPZ Jb
指令长度: 两个字节
ECX = ECX - 1
当ZF = 1 && ECX != 0 时跳转到当前指令地址 + 当前指令长度 + Jb
(3) 0xE2
LOOP Jb
指令长度: 两个字节
ECX = ECX - 1
当 ECX!=0 时跳转到当前指令地址 + 当前指令长度 + Jb
(4) 0xE3
JrCXZ Jb (在32位模式中,rCX为ECX; 在64位模式中,rCX为RCX)
指令长度: 两个字节
当 ECX = 0 时跳转到当前指令地址 + 当前指令长度 + Jb
执行前后ECX不会自动改变,需要自己手动控制步长
(5) 0xE8
CALL Jd
指令长度: 五个字节
CALL指令的下一条指令地址入栈后,跳转到当前指令地址 + 当前指令长度 + Jd
(6) 0xE9
JMP Jd
指令长度: 五个字节
跳转到当前指令地址 + 当前指令长度 + Jd
(7) 0xEA
JMP Ap (Ap: 六字节长度的直接地址)
指令长度: 七个字节
JMP CS:Id 将imm48中的高2位赋值给CS,低4位直接赋值给EIP
EA 12345678 1B00 ---> jmp far 1B:78563412
(8) 0xEB
JMP Jb
指令长度: 两个字节
跳转到当前指令地址 + 当前指令长度 + Jb
(9) 0xC3
RET
指令长度: 一个字节
EIP出栈
(10) 0xC2
RET Iw
指令长度: 三个字节
EIP出栈后,ESP = ESP + Iw
(11) 0xCB
RETF (return far)
指令长度: 一个字节
长调用且跨段不提权时
pop eip
pop cs
(12) 0xCA
RETF Iw
指令长度: 三个字节s
长调用且跨段不提权时
pop eip
pop cs
ESP = ESP + Iw
