硬编码学习笔记(一)—— 经典定长指令
前言
本次学习仅基于intel x86模式
指令结构
描述:对于任何一条指令,都由以下几部分组成,但不是每部分都必须存在
长度:最短1个字节,最长15个字节
Instruction Prefixes:指令前缀
Opcode: 主操作码
ModR/M:在内存中引用一个操作数的许多指令都有一个寻址方式的指定符字节(称为ModR/M字节)跟随在主操作码之后
SIB:ModR/M字节的某些编码需要第二个寻址字节(SIB字节)
Displacement:一些寻址方式包含紧跟ModR/M字节(或者SIB字节,如果有的话)的位移
Immediate:立即数
符号说明
寻址符号
符号意义A直接寻址
C控制寄存器
D调试寄存器
E寄存器/内存
FEFLAGS/RFLAGS寄存器
G通用寄存器
I立即数
J要添加到指令指针寄存器的相对偏移量
MModR/M字节可能仅指向内存。
NMMX 技术寄存器
O该指令没有ModR/M字节。操作数的偏移量在指令中被编码为一个字或双字(取决于地址大小属性)。
PModR/M字节的reg字段选择一个打包的四字MMX技术寄存器
QModR/M字节跟随操作码并指定操作数。该操作数要么是MMX技术寄存器,要么是内存地址。
RModR/M字节的R/M字段可能仅指一个通用寄存器
SModR/M字节的reg字段选择一个段寄存器
UModR/M字节的R/M字段选择一个128位的XMM寄存器。
VModR/M字节的reg字段选择一个128位的XMM寄存器。
WModR/M字节跟随操作码并指定操作数。操作数要么是一个128位的XMM寄存器要么是一个内存地址。
X由DS:rSI寄存器对寻址的内存
Y由ES:rDI寄存器对寻址的内存
操作数符号
符号意义a内存中的两个单字操作数或内存中的两个双字操作数,具体取决于操作数大小属性(仅由BOUND指令使用)
b字节
c字节/字
d双字
dq四字
p32位/48位/80位指针
pd128位封装的双精度浮点数据
pi双四字,MMX技术寄存器(例如:mm0)
ps128位封装的单精度浮点数据
q四字
s6字节或10字节的伪描述符
ss128位打包的单精度浮点数据的标量元素
si双字整数寄存器(例如:eax)
v字、双字或四字(取决于当前CPU的模式)
w字
z16位操作数大小的字或32位或64位操作数大小的双字
上标符号
符号意义1AModR/M字节的第5、4和3位用作操作码扩展
1B使用0F0B操作码(UD2指令)或0FB9H操作码时,故意尝试生成无效的操作码异常(#UD)
1C在Pentium III处理器中添加的一些指令可以使用相同的双字节操作码。如果指令有变化,或者操作码代表不同的指令,则使用ModR/M字节来区分指令。
i64该指令无效或在64位模式下不可编码。40到4F(单字节INC和DEC)是64位模式下的REX前缀组合(对INC和DEC使用FE/FF Grp 4和5)。
o64指令仅在64位模式下可用。
d64当处于64位模式时,指令默认为64位操作数大小,并且不能对32位操作数大小进行编码。
f64在64位模式下,操作数大小被强制为64位操作数大小(在64位模式下,该指令会忽略改变操作数大小的前缀)。
One-Byte Opcode Map
经典定长指令:修改寄存器
0x40~0x47
指令长度:共1个字节
40INC EAX
41INC ECX
42INC EDX
43INC EBX
44INC ESP
45INC EBP
46INC ESI
47INC EDI
0x48~0x4F
指令长度:共1个字节
48DEC EAX
49DEC ECX
4ADEC EDX
4BDEC EBX
4CDEC ESP
4DDEC EBP
4EDEC ESI
4FDEC EDI
0x50~0x57
指令长度:共1个字节
50PUSH EAX
51PUSH ECX
52PUSH EDX
53PUSH EBX
54PUSH ESP
55PUSH EBP
56PUSH ESI
57PUSH EDI
0x58~0x5F
指令长度:共1个字节
58POP EAX
59POP ECX
5APOP EDX
5BPOP EBX
5CPOP ESP
5DPOP EBP
5EPOP ESI
5FPOP EDI
0x90~0x97
指令长度:共1个字节
90NOP//XCHG EAX, EAX
91XCHG EAX,ECX
92XCHG EAX,EDX
93XCHG EAX,EBX
94XCHG EAX,ESP
95XCHG EAX,EBP
96XCHG EAX,ESI
97XCHG EAX,EDI
0xB0~0xB7
指令长度:共2个字节
B0 00MOV AL,0x0
B1 01MOV CL,0x1
B2 02MOV DL,0x2
B3 03MOV BL,0x3
B4 04MOV AH,0x4
B5 05MOV CH,0x5
B6 06MOV DH,0x6
B7 07MOV BH,0x7
0xB8~0xBF
指令长度:共5个字节
B8 00 00 00 10MOV EAX,0x10000000
B9 01 00 00 10MOV ECX,0x10000001
BA 02 00 00 10MOV EDX,0x10000002
BB 03 00 00 10MOV EBX,0x10000003
BC 04 00 00 10MOV ESP,0x10000004
BD 05 00 00 10MOV EBP,0x10000005
BE 06 00 00 10MOV ESI,0x10000006
BF 07 00 00 10MOV EDI,0x10000007
经典定长指令:修改EIP
0x70~0x7F
指令长度:共2个字节
偏移量:1个字节
当偏移量<0x80时:EIP = 当前指令地址+当前指令长度+偏移量
当偏移量>0x80时:EIP = 当前指令地址+当前指令长度-偏移量
70JO
71JNO
72JB/JNAE/JC
73JNB/JAE/JNC
74JZ/JE
75JNZ/JNE
76JBE/JNA
77JNBE/JA
78JS
79JNS
7AJP/JPE
7BJNP/JPO
7CJL/JNGE
7DJNL/JGE
7EJLE/JNG
7FJNLE/JG
0x0F80~0x0F8F
指令长度:共6个字节
偏移量:4个字节
EIP = 当前指令地址+当前指令长度+偏移量
0F80JO
0F81JNO
0F82JB/JNAE/JC
0F83JNB/JAE/JNC
0F84JZ/JE
0F85JNZ/JNE
0F86JBE/JNA
0F87JNBE/JA
0F88JS
0F89JNS
0F8AJP/JPE
0F8BJNP/JPO
0F8CJL/JNGE
0F8DJNL/JGE
0F8EJLE/JNG
0F8FJNLE/JG
0xE0
指令长度:共2个字节
LOOPNE/LOOPNZ Ib(Jb)
当ZF==0&&ECX!=0时:EIP=当前指令地址+当前指令长度+Ib;ECX=ECX-1
0xE1
指令长度:共2个字节
LOOPE/LOOPZ Ib(Jb)
当ZF==1&&ECX!=0时:EIP=当前指令地址+当前指令长度+Ib;ECX=ECX-1
0xE2
指令长度:共2个字节
LOOP Ib(Jb)
当ECX!=0时:EIP=当前指令地址+当前指令长度+Ib;ECX=ECX-1
0xE3
指令长度:共2个字节
JrCXZ Ib(Jb)//在32位模式中,rCX为ECX
当ECX==0时:EIP=当前指令地址+当前指令长度+Ib
0xE8
指令长度:共5个字节
CALL Id(Jd)
下一条指令地址入栈;EIP=当前指令地址+当前指令长度+Id
0xE9
指令长度:共5个字节
JMP Id(Jd)
EIP=当前指令地址+当前指令长度+Id
0xEA
指令长度:共7个字节
JMP Ap//Ap为六字节长度的直接地址
JMP CS:Id//将Ap中的高2位赋值给CS,低4位赋值给EIP
0xEB
指令长度:共2个字节
JMP Ib(Jb)
EIP=当前指令地址+当前指令长度+Ib
0xC2
指令长度:共3个字节
RET Iw//POP EIP;ESP=ESP+Iw
0xC3
指令长度:共1个字节
RET//POP EIP
0xCA
指令长度:共1个字节
RETF//POP EIP;POP CS
0xCB
指令长度:共3个字节
RETF Iw//POP EIP;POP CS;ESP=ESP+Iw
标签:编码,00,字节,操作数,笔记,指令,长度,ECX
来源: https://blog.csdn.net/qq_41988448/article/details/115353466