Intel IA-32 / Intel 64 指令架構 之 指令解碼
引言:
-------------------------------------
IA-32 到 Intel 64 架構中每一條匯編指令也由特定的格式給CPU的指令解碼器,或調試器的反匯編器(disassembler)解析,因而我們可以直觀地知道這些指令,第一層人類有能力看得懂的語言,其中每條指令由以下組件組成:
1. Instruction prefixes(指令前輟):
-------------------------------------
指令前輟分為4組:
Group 1 :
- Lock/repeat prefix :
F0h : LOCK prefix
F2h : REPNE/REPNZ
F3h : REP or REPE/REPZ , F3h prefix 更預設用在POPCNT,LZCNT,ADOX指令上
- Bound prefix :
Group 2:
- Segment override prefix:
2Eh - CS segment override
36h - SS segment override
3Eh - DS segment override
26h - ES segment override
64h - FS segment override
65h - GS segment override
- Branch hints(分支)
2Eh - 分支沒效,只有jcc指令使用
3Eh - 分支有效,只有jcc指令使用
Group 3 :
66h - Operand-size override
Group 4 :
67h - address-size override
LOCK prefix - 強制向cpu發送LOCK#信號,確保原子操作
Repeat prefix - 重覆執行指定指令 比如movs, cmps, scas, lods, stos, ins, outs
Branch hint prefix - 用於提醒CPU,最有可能的執行路徑(分支)
Operand/address-size override prefix - 用於尋址時,operand/內存的16bit / 32bit大小切換
2. Opcode (操作碼):
-------------------------------------
Opcode 亦即操作碼,即該指令實際要執行的動作;其大小最大為1~3 byte , 如果操作需要,另外會有3-bit opcode信息被加到ModR/M field
2-byte opcode: 一般由 0F 填充 + 任意byte組成 , prefix 分別可以是66H, F2H, F3H
如: CVTDQ2PD指令: F3 0F E6
3-byte opcode: 一般由 0F 填充 + 住意2byte組成 ,prefix 分別可以是66H,F2H ,F3H
如: XMM指令集中的PHADDW : 66 0F 38 01
ModR/M and SIB bytes:
它們只占2byte, 各占1byte, 很多指令一般需要使用操作數operand,處理器在解析指令其間需要進行解碼,才知道指令的"參數"
ModR/M - 1byte :
mod[7:6]: 與r/m位組成32種可能性,(指的是8個通用寄存器/24種尋址模式)
reg/opcode[5:3] : 指通用寄存器號碼 / 3bit外加opcode信息 (被寫入的寄存器)
R/M[2:0]: 可以指的是register 或與 mod位組成一個尋址模式 並定義出主要寄存器
即mod位 + REG位 + r/m位
ModR/M 取參數的基本組成原理,以32bit為例:
Reg映射表格:
####################################
AL CL DL BL AH BH DH CH
AX CX DX BX SP BP SI DI
EAX ECX EDX EBX ESP EBP ESI EDI
MM0 MM1 MM2 MM3 MM4 MM5 MM6 MM7
XMM0 XMM1 XMM2 XMM3 XMM4 XMM5 XMM6 XMM7
REG: 000b 001b 010b 011b 100b 101b 110b 111b
#####################################
32位尋址模式映射表格:
#####################################
mod: 00b R/M
[EAX] : 000b
[ECX] : 001b
[EDX] : 010b
[EBX] : 011b
[--][--] : 100b
disp32 : 101b
[ESI] : 110b
[EDI] : 111b
mod: 01b R/M
[EAX]+disp8 : 000b
[ECX]+disp8 : 001b
[EDX]+disp8 : 010b
[EBX]+disp8 : 011b
[--][--]+disp8 : 100b
[EBP]+disp8 : 101b
[ESI]+disp8 : 110b
[EDI]+disp8 : 111b
mod: 10b R/M
[EAX]+disp32 : 000b
[ECX]+disp32 : 001b
[EDX]+disp32 : 010b
[EBX]+disp32 : 011b
[--][--]+disp32 : 100b
[EBP]+disp32 : 101b
[ESI]+disp32 : 110b
[EDI]+disp32 : 111b
mod: 11b R/M
EAX/AX/AL/MM0/XMM0 : 000b
ECX/CX/CL/MM1/XMM1 : 001b
EDX/DX/DL/MM2/XMM2 : 010b
EBX/BX/BL/MM3/XMM3 : 011b
ESP/SP/AH/MM4/XMM4 : 100b
EBP/BP/CH/MM5/XMM5 : 101b
ESI/SI/DH/MM6/XMM6 : 110b
EDI/DI/BH/MM7/XMM7 : 111b
#####################################
如:mov eax, [EBP + displacement8 /r8] = 8b 45 08
這裡的45h 表示的其實是
mod = 1 ;
r/m = [ebp+disp8] = 101 ; 此模式表示緊隨其後的是SIB byte就是8
reg = 000 ; 是否選用eax/ax/al/xmm0/mm0 是基于opcode的原因
mod + reg + r/m = 01000101 = 45h
因而產生出參數是 45 08
而操作數是: 8b 則採用rax/eax/ax 或 可能是r8寄存器(Intel 64架構), 這取決於cpu結構
因此IA-32架構下最終指令為 : 8b 45 08 | mov eax, [ebp+0x8]
假如我們想把參數[ebp+0x8h] 改為ebx, 即mov eax, ebx指令, 把尋址模式改變即可(即改變mod位 跟r/m 位)
mod = 11h
r/m = 011
11000011 = C3h
指令則變成: 8b C3 p.s. 由於沒有displacement 08h 自動去掉
3. SIB byte:
ModR/M byte需要下一級的2級參數的解析,base-plus-index / scale-plus-index
Scale[7:6]: 指的是scale factor
Index[5:3]: 指的是寄存器索引
Base [2:0]: 指的是基礎寄存器索引
首先也來一張解碼表:
Base 映射表格:
#####################################
EAX ECX EDX EBX ESP [*] ESI EDI
Base: 000 001 010 011 100 101 110 111
scale 映射表格:
#####################################Scaled Index | SS | Index |
EAX 00 000
ECX 001
EDX 010
EBX 011
non 100
EBP 101
ESI 110
EDI 111
Scaled Index | SS | Index |
EAX*2 01 000
ECX*2 001
EDX*2 010
EBX*2 011
non 100
EBP*2 101
ESI*2 110
EDI*2 111
#####################################
p.s. 避免篇幅太長 *4 / *8 只是改變了ss
SS + Index + Base : 如 : 00 001 001 則代表是 [ecx+ecx]
如: 8b 04 09 | mov eax, dword ptr[ecx+ecx] ; 8Bh表示opcode操作碼及目的地寄存器為mov eax,
; 04h則表示參數的尋址模式為[--][--],即來源為寄存器並需要非固定displacement
; 09h則決定哪兩個寄存器成為參數如: ecx+ecx
SIB byte生效的前提是:
當ModR/M尋址模式是[--][--] / [--][--]+disp時: SIB byte則取替其功效
而[--][--]+disp模式就必須在SIB byte後,緊接著displacement
如: 8b 44 40 08 | mov eax, dword ptr [eax+eax*2+8h]
對以下3項作出了64位的兼容
-------------------------------------
IA-32 到 Intel 64 架構中每一條匯編指令也由特定的格式給CPU的指令解碼器,或調試器的反匯編器(disassembler)解析,因而我們可以直觀地知道這些指令,第一層人類有能力看得懂的語言,其中每條指令由以下組件組成:
1. Instruction prefixes(指令前輟):
-------------------------------------
Group 1 :
- Lock/repeat prefix :
F0h : LOCK prefix
F2h : REPNE/REPNZ
F3h : REP or REPE/REPZ , F3h prefix 更預設用在POPCNT,LZCNT,ADOX指令上
- Bound prefix :
Group 2:
- Segment override prefix:
2Eh - CS segment override
36h - SS segment override
3Eh - DS segment override
26h - ES segment override
64h - FS segment override
65h - GS segment override
- Branch hints(分支)
2Eh - 分支沒效,只有jcc指令使用
3Eh - 分支有效,只有jcc指令使用
Group 3 :
66h - Operand-size override
Group 4 :
67h - address-size override
LOCK prefix - 強制向cpu發送LOCK#信號,確保原子操作
Repeat prefix - 重覆執行指定指令 比如movs, cmps, scas, lods, stos, ins, outs
Branch hint prefix - 用於提醒CPU,最有可能的執行路徑(分支)
Operand/address-size override prefix - 用於尋址時,operand/內存的16bit / 32bit大小切換
2. Opcode (操作碼):
-------------------------------------
2-byte opcode: 一般由 0F 填充 + 任意byte組成 , prefix 分別可以是66H, F2H, F3H
如: CVTDQ2PD指令: F3 0F E6
3-byte opcode: 一般由 0F 填充 + 住意2byte組成 ,prefix 分別可以是66H,F2H ,F3H
如: XMM指令集中的PHADDW : 66 0F 38 01
ModR/M and SIB bytes:
它們只占2byte, 各占1byte, 很多指令一般需要使用操作數operand,處理器在解析指令其間需要進行解碼,才知道指令的"參數"
ModR/M - 1byte :
mod[7:6]: 與r/m位組成32種可能性,(指的是8個通用寄存器/24種尋址模式)
reg/opcode[5:3] : 指通用寄存器號碼 / 3bit外加opcode信息 (被寫入的寄存器)
R/M[2:0]: 可以指的是register 或與 mod位組成一個尋址模式 並定義出主要寄存器
即mod位 + REG位 + r/m位
ModR/M 取參數的基本組成原理,以32bit為例:
Reg映射表格:
####################################
AL CL DL BL AH BH DH CH
AX CX DX BX SP BP SI DI
EAX ECX EDX EBX ESP EBP ESI EDI
MM0 MM1 MM2 MM3 MM4 MM5 MM6 MM7
XMM0 XMM1 XMM2 XMM3 XMM4 XMM5 XMM6 XMM7
REG: 000b 001b 010b 011b 100b 101b 110b 111b
#####################################
32位尋址模式映射表格:
#####################################
mod: 00b R/M
[EAX] : 000b
[ECX] : 001b
[EDX] : 010b
[EBX] : 011b
[--][--] : 100b
disp32 : 101b
[ESI] : 110b
[EDI] : 111b
mod: 01b R/M
[EAX]+disp8 : 000b
[ECX]+disp8 : 001b
[EDX]+disp8 : 010b
[EBX]+disp8 : 011b
[--][--]+disp8 : 100b
[EBP]+disp8 : 101b
[ESI]+disp8 : 110b
[EDI]+disp8 : 111b
mod: 10b R/M
[EAX]+disp32 : 000b
[ECX]+disp32 : 001b
[EDX]+disp32 : 010b
[EBX]+disp32 : 011b
[--][--]+disp32 : 100b
[EBP]+disp32 : 101b
[ESI]+disp32 : 110b
[EDI]+disp32 : 111b
mod: 11b R/M
EAX/AX/AL/MM0/XMM0 : 000b
ECX/CX/CL/MM1/XMM1 : 001b
EDX/DX/DL/MM2/XMM2 : 010b
EBX/BX/BL/MM3/XMM3 : 011b
ESP/SP/AH/MM4/XMM4 : 100b
EBP/BP/CH/MM5/XMM5 : 101b
ESI/SI/DH/MM6/XMM6 : 110b
EDI/DI/BH/MM7/XMM7 : 111b
#####################################
如:mov eax, [EBP + displacement8 /r8] = 8b 45 08
這裡的45h 表示的其實是
mod = 1 ;
r/m = [ebp+disp8] = 101 ; 此模式表示緊隨其後的是SIB byte就是8
reg = 000 ; 是否選用eax/ax/al/xmm0/mm0 是基于opcode的原因
mod + reg + r/m = 01000101 = 45h
因而產生出參數是 45 08
而操作數是: 8b 則採用rax/eax/ax 或 可能是r8寄存器(Intel 64架構), 這取決於cpu結構
因此IA-32架構下最終指令為 : 8b 45 08 | mov eax, [ebp+0x8]
假如我們想把參數[ebp+0x8h] 改為ebx, 即mov eax, ebx指令, 把尋址模式改變即可(即改變mod位 跟r/m 位)
mod = 11h
r/m = 011
11000011 = C3h
指令則變成: 8b C3 p.s. 由於沒有displacement 08h 自動去掉
3. SIB byte:
-------------------------------------
SIB byte = Scale + Index + base ModR/M byte需要下一級的2級參數的解析,base-plus-index / scale-plus-index
Scale[7:6]: 指的是scale factor
Index[5:3]: 指的是寄存器索引
Base [2:0]: 指的是基礎寄存器索引
首先也來一張解碼表:
Base 映射表格:
#####################################
EAX ECX EDX EBX ESP [*] ESI EDI
Base: 000 001 010 011 100 101 110 111
#####################################
#####################################Scaled Index | SS | Index |
EAX 00 000
ECX 001
EDX 010
EBX 011
non 100
EBP 101
ESI 110
EDI 111
Scaled Index | SS | Index |
EAX*2 01 000
ECX*2 001
EDX*2 010
EBX*2 011
non 100
EBP*2 101
ESI*2 110
EDI*2 111
#####################################
p.s. 避免篇幅太長 *4 / *8 只是改變了ss
SS + Index + Base : 如 : 00 001 001 則代表是 [ecx+ecx]
如: 8b 04 09 | mov eax, dword ptr[ecx+ecx] ; 8Bh表示opcode操作碼及目的地寄存器為mov eax,
; 04h則表示參數的尋址模式為[--][--],即來源為寄存器並需要非固定displacement
; 09h則決定哪兩個寄存器成為參數如: ecx+ecx
SIB byte生效的前提是:
當ModR/M尋址模式是[--][--] / [--][--]+disp時: SIB byte則取替其功效
而[--][--]+disp模式就必須在SIB byte後,緊接著displacement
如: 8b 44 40 08 | mov eax, dword ptr [eax+eax*2+8h]
4. IA-32e
----------------------------------
----------------------------------
IA-32e模式 即64位下,唯一不同是增加了REX prefix
-
GPRs and SSE.
-
64-bit operand大小.
-
extended 控制寄存器.
----------------------------------
Comments
Post a Comment