1. 何爲OPCodejava
在計算機科學領域中,操做碼(Operation Code, OPCode)被用於描述機器語言指令中,指定要執行某種操做的那部分機器碼,構成OPCode的指令格式和規範由處理器的指令規範指定。除了指令自己之外一般還有指令所須要的操做數,可能有的指令不須要顯示的操做數。這些操做數多是寄存器中的值,堆棧中的值,某塊內存的值或者IO端口中的值等等。
OPCode在不一樣的場合中一般具備不一樣的含義,例如PHP虛擬機(Zend VM)、java虛擬機(JVM)以及一些軟件保護虛擬機中的最小操做單元均可以稱之爲OPCode。
2. 經常使用單字節OPCode概覽A -- 40~4F
opcode asm using
0x40 inc eax emit(0x40)
0x41 inc ecx emit(0x41)
0x42 inc edx emit(0x42)
0x43 inc ebx emit(0x43)
0x44 inc esp emit(0x44)
0x45 inc ebp emit(0x45)
0x46 inc esi emit(0x46)
0x47 inc edi emit(0x47)
2. 經常使用單字節OPCode概覽B -- 50~5F
2. 經常使用單字節OPCode概覽C -- 70~7F
opcode asm using
0x70 0x12 Jo 0x12 {_emit(0x70)} {_emit(0x12)}
0x71 ... Jno ... ... ...
0x72 ... Jb ... ... ...
0x73 ... Jae ... ... ...
0x74 ... Je ... ... ...
0x75 ... Jne ... ... ...
0x76 ... Jbe ... ... ...
0x77 ... Ja ... ... ...
0x78 ... Js ... ... ...
0x79 ... Jns ... ... ...
0x7a ... Jp ... ... ...
0x7b ... Jnp ... ... ...
0x7c ... Jl ... ... ...
0x7d ... Jge ... ... ...
0x7e ... Jle ... ... ...
0x7f ... Jg ... ... ...
2. 經常使用單字節OPCode概覽D -- 90~9F
Opcode asm Using
0x90 Nop/xchg eax,eax _emit(0x90)
3. OPCode與指令的對應關係
4. OPCode詳解A -- 主要數據域
以上數據域只有Code域是必須存在的,其餘數據域視指令格式而定,或有或無
一個指令的長度在1Byte~16Byte之間
實際正常的最長指令是,13Byte
4. OPCode詳解B -- 前綴
前綴(Prefixes)的大小爲1Byte,用於描述指令的前綴狀況,他們能夠被劃分爲5個集合:
66 -- 切換操做數大小
67 -- 切換地址大小
F2/F3 -- 重複操做前綴
2E/36/3E/26/64/65 -- 修改默認段
F0 -- 鎖定前綴
因此指令獨此一份,不可能爲其餘機器碼
注意:
a. "切換"的意思是將其在兩種狀態間來回切換,而並不是特指某種狀態
b. 將默認值修改成其餘段的操做稱之爲"修改默認段"
c. 一個OpCode可能會有幾個Prefixes
d. 若是有多個Prefixes,那麼它們的順序可能打亂
e. 若是Prefixes不能對隨它以後的OpCode起做用,那麼它就會被忽略
4. OPCode詳解C -- 前綴
切換操做數大小
40 INC EAX
66 40 INC AX
切換順序: 從大到小
無效的前綴應用
8AC1 MOV AL, CL
66 BAC1 MOV AL, CL
重複操做段前綴
F3 66 AD REP LODSW
F2 AC REPNE LODSB
段超越前綴
8B 03 MOV EAX, [DWORD DS:EBX]
658B 03 MOV EAX, [DWORD GS:EBX]
4. OPCode詳解D -- ModR/M
OPCode的主要解析邏輯都集中在ModR/M域,咱們能夠經過對照Intel手冊中的表來解析OPCode中的ModR/M域來肯定指令的具體格式
例如:
89 D8 mov eax, ebx
D8 = 11011000
Mod Reg R/M
11 011 000
4. OPCode詳解E -- Opcode小注
/0~7: 此ModR/M只使用R/M域的信息
/r : 此ModR/M同時使用R/M域與Reg域信息
+rb: 寄存器碼, 此碼將加載OPCode原有值上
AL = 0, CL = 1, DL = 2, BL = 3, AH = 4, CH = 5, DH = 6, BH = 7
+rw: 寄存器碼,此碼將加載OPCode原有值上
AX = 0, CX = 1, DX = 2, BX = 3, SP = 4, BP = 5, SI = 6, DI = 7
+rd: 寄存器碼,此碼將加載OPCode原有值上
EAX = 0, ECX = 1, EDX = 2, EBX = 3, ESP = 4, EBP = 5, ESI = 6, EDI = 7
+i: 僅限於浮點計算時,增長的數能夠是0~7, 用於標記當前使用的FPU
堆棧,此碼將加載OPCode原有值上
4. OPCode詳解F -- 高大上指令賞析
13字節彙編指令賞析
F0:26:C7 8491AA000000 11000000
LOCK MOV DWORD PTR ES: [EDX*4 + ECX + 0AA], 11
Prefix OPCode ModR/M SIB Displacement Immediate
F0:26: C7 84 91 AA000000 01000000
注1 注2 注3 注4 偏移 當即數
注1: 鎖定前綴 + ES段超越
注2: MOV r/m32, imm32
注3: R/M = disp32[--][--] Mod != EAX
注4: Index = [EDX*4] r32 = ECX
84 91 AA000000 --> [EDX*4 + ECX +0xAA]
5. 練習
①. 83C4 04
分析:
83 /0 ib: ADD r/m32,imm8 ;/0~7 只使用R/M信息
C4: ESP
結果:
add esp, 04
②. A1 78812801
A1 : MOV EAX,moffs32* ;Move doubleword at (seg:offset) to EAX, moffs32爲32位地址
結果:
mov eax, dword ptr ds:[1288178]
③. A3 54812801
A3 MOV moffs32*,EAX ;Move EAX to (seg:offset),moffs32爲32位地址
結果:
mov dword ptr ds:[1288154], eax
④. 68 54812801
PUSH imm32
結果:
push 1288154
⑤. 8B0D 74812801
8B /r MOV r32,r/m32 ;/r 同時使用R/M域與Reg域信息
OD 有效地址: disp32 REG: ECX
結果:
mov ecx, dword ptr ds:[1288174]
⑥. 51
50+rdPUSH r32 ;EAX = 0, ECX = 1, EDX = 2, EBX = 3, ESP = 4, EBP = 5, ESI = 6, EDI = 7
結果:
push ecx
⑦. 68 48812801
68 PUSH imm32
結果:
push 1288148
⑧. FF15 A4922801
FF /3CALL m16:32 ;/0~7 只使用R/M信息
15 有效地址: disp32
結果:
call dword ptr cs:[12892A4]
總結:
ModR/M信息與確認是否有SIB字節
當Mod != 11b而且R/M的值爲100b的時候,表示指令後續有SIB字節,而且該內存操做對象由SIB編碼。
MODR/M裏有三種狀況會有SIB字節