OpCode(操作码) 和 mnemonic(助记符) 是多对多的
OpCode由6个域组成,其中code是必须的,其他是可选的
a. Prefixes b. code c. ModR/M d. SIB e. Displacement f. Immediate
a. 前缀 b. 操作码 c. ModR/M d. SIB e. Displacement f. 立即数
AAM AL 除以 10 AL 商 AH 余数
AAD AL = AH * 10 + AL
EIP 存储了内存中的某个地址,这个地址告诉CPU,哪里是当前指令的开始,
但是在指令解码前,不知道哪里是指令的结束
1.
00401000 90 NOP
EIP OpCode mnemonic
解码以后,由于知道NOP只有一个字节,EIP = EIP + 指令的长度(1+1)=00400001
2.
00401000 EB 00 JMP 00401002
00401002 90 NOP
EB占用1个字节,00占用1个字节,EIP = EIP + 指令的长度(1+1)=00400002
3.
00401000 EB FE JMP 00401000
00401002 90 NOP
EB占用1个字节,FE占用1个字节,EIP = EIP + 指令的长度(1+1)=0xFE+0x2=0x100
由于imm8的关系,0x100只能取00,2个字节的情况下,只能取低1个字节。
真正的底层程序员应该会理解指令的本质,而不仅仅是从指令的字面上去理解它的意思。
4.
00401000 75 01 JNZ SHORT 3 ->
如果不是0,那么EIP的值是 EIP当前值(00401000)
+ 本条指令的立即数(01)+本条指令的长度(2)
00401002 04 AC ADD AL, 0AC
所以会跳到04 AC的中间执行
Perfixes 前缀:
1. 所有Prefixes的长度都是1个字节。
2. 一个OpCode可能会有几个Prefixes。
3. 如果有多个Prefixes,那么它们的顺序可以打乱。
4. 如果Prefixes不能对随它之后的OpCode起作用,那么它就会被忽略。
Perfixes分类:
1. Change DEFAULT operand size.(66) 切换默认操作数大小,是开关标记
2. Change DEFAULT address size.(67) 切换默认地址的大小,是开关标记
3. Repeat prefixes.(F2 F3) 重复前缀
4. Segment override prefixes (change DEFAULT segment).
2E - CS 36 - SS 3E - DS 26 - ES 64 - FS 65 - GS
5. LOCK prefix.(F0) 锁前缀
例:8A 00 MOV AL, [EAX] -> 67 8A 00 MOV AL, [BX+SI]
地址由原来的32位的[EAX]变成了16位的[BX+SI]
在16位的地址模式中无法完全使用32位中的对应的地址模式,
两种模式中的寄存器有着一定的区别。
Repeat Prefixes(F2 F3)
Repeat Prefixes通常是与movs scas cmps 等串指令搭配使用
F2 REPNE F3 REP/REPE
重复执行后面的串操作指令,每次重复前先判断(E)CX的值,> 0 把(E)CX的值减1,
再重复执行后面的串操作指令 =0退出
和LOOP指令的区别是:LOOP指令先把(E)CX的值减1,再判断是否为0
有3种Repeat Prefixes的助记符:rep/repe/repene,但是只有2个OpCode:F2 F3
如果某些指令只使用前缀rep,那么这里的rep可以用repe或者repne来代替
重复串指令时可能会改变某些标志位(例如ZF),在这种情况下,有些指令与重复前缀
搭配使用时,F2和F3会把最后一位与标志位ZF进行比较,
如果它们不相同,则重复串指令的操作将会结束。而有些指令不用进行这个比较的操作,
因此标志位ZF对这些指令的运行结果无影响。
11110010 F2 11110011 F3
Repeat Prefixes的结束条件 REP = ECX=0 REPE = ECX=0 && ZF=0 REPNE = ECX=0 && ZF=1
CS: For EIP pointer
ES: 目的操作数是内存单元的串指令(movs, cmps等),在这里源操作数是储存在段DS里面
SS: 堆栈操作(push, pop等)
DS: 剩下的数据操作指令
FS一般是由SEH(结构化异常处理)所使用
1个字节如果被转换成2进制,是由8bit来表示,不足8bit高位补0
ModR/M是由Mod Reg/Opcode R/M三个部分组成的
每个部分所占的bit大小为:
Mod: 6 7
Reg/Opcode: 3 4 5
R/M: 0 1 2
分析下面2条机器指令
8B F9(MOV EDI, ECX) 2B F9(SUB EDI, ECX)
因为没有前缀,F9是MOD Reg/OpCode R/M, F9(11111001)按照2:3:3拆开,
MOD=11
Reg/OpCode=111
/ 表示或,意思是这个地方可以表示为Reg或OpCode(由Code来决定),
如果它是表示OpCode,则这个指令必定是2字节的。
Reg由3个bit组成,所以有8种可能:
000 - EAX 001 - ECX 010 - EDX 011 - EBX 100 - ESP
101 - EBP 110 - ESI 111 - EDI
R/M=001
结论
Mod=11 表示应该查看Mod为11的那一栏
Reg/Opcode=111 表示的是寄存器EDI
R/M=001 表示的是ECX