日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

硬编码学习笔记(二)—— 经典变长指令

發布時間:2025/3/21 编程问答 19 豆豆
生活随笔 收集整理的這篇文章主要介紹了 硬编码学习笔记(二)—— 经典变长指令 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

硬編碼學習筆記(二)—— 經典變長指令

  • 前言
  • 指令結構
  • 符號說明
    • 尋址符號
    • 操作數符號
    • 上標符號
  • One-Byte Opcode Map
  • 變長指令
  • ModR/M
    • 例:0x88
    • 例:0x89
    • 例:0x8A
    • 例:0x8B
  • SIB
    • 例:88 84 48 78 56 34 12
    • 例:89 84 84 78 56 34 12
  • Opcode Extension Tables
  • 例:80 65 08 FF
  • Instruction Prefixs
    • 段前綴
    • 操作指令前綴:修改地址默認長度
    • 操作指令前綴:修改默認尋址方式

前言

本次學習僅基于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位模式下無效
o64指令僅在64位模式下有效
d64當處于64位模式時,指令默認為64位操作數大小,并且不能對32位操作數大小進行編碼。
f64在64位模式下,操作數大小被強制為64位操作數大小(在64位模式下,該指令會忽略改變操作數大小的前綴)。

One-Byte Opcode Map


變長指令

描述:當操作系統遇到諸如0x88這樣的Opcode時,其指令序列為MOV Eb, Gb,目的是將一個8位的寄存器存儲到一個8位的寄存器或內存中,當表中出現E或G這樣的符號時,即存在ModR/M字段

思考:CPU如何知道要把值放在哪個寄存器中?
答案:使用ModR/M字段

ModR/M

描述:指令在引用一個不確定操作數時使用該字段進行定位

結構

Reg/Opcode:用來確定寄存器或操作碼是什么
Mod+R/M:這兩個字段拼在一起確定是哪個內存或寄存器

例:0x88

指令格式:MOV Eb, Gb

:88 00

Mod:00 Reg/Opcode:000 //使用0號寄存器,是EAX還是AL由操作碼決定 R/M:000 //Mod與R/M拼在一起指向[EAX]

因此字節碼88 00對應的指令為:MOV [EAX], AL

注意

  • 當Mod為00,R/M為100時,使用另一種指令格式
  • 當Mod為00,R/M為101時,向后再取4字節立即數作為Gb的值88 15 00 10 40 00 MOV [0x401000],DL
  • 例:0x89

    指令格式:MOV Ev, Gv

    :89 49 10

    Mod:01 Reg/Opcode:001 //使用1號寄存器 R/M:001 //Mod與R/M拼在一起指向[ECX]+disp8


    因此字節碼89 49 10對應的指令為:MOV [ECX+0x10], ECX

    例:0x8A

    指令格式:MOV Gb, Eb

    :8A 92 78 56 34 12

    Mod:10 Reg/Opcode:010 //使用2號寄存器 R/M:010 //Mod與R/M拼在一起指向[EDX]+disp32


    因此字節碼8A 92 78 56 34 12對應的指令為:MOV DL, [EDX+0x12345678]

    例:0x8B

    指令格式:MOV Gv, Ev

    :8B DB

    Mod:11 Reg/Opcode:011 //使用3號寄存器 R/M:011 //Mod與R/M拼在一起指向EBX


    因此字節碼8B DB對應的指令為:MOV EBX, EBX

    SIB

    描述

  • Opcode決定了后邊是否存在ModR/M字段,而ModR/M決定了后面是否存在SIB字段
  • 當ModR/M字段低3位為100時,存在SIB字段
  • 結構

    Scale: 2的幾次方
    Index:下標
    Base:確定是哪個寄存器

    例:DS:[EAX+ECX2+0x12345678]
    scale表示21
    Index表示ECX
    Base表示EAX
    0x12345678由ModR/M字段決定
    即:SIB=Base+Index2的scale次方

    [*]:取決于ModR/M中MOD字段的值
    00 [scaled index] + disp32
    01 [scaled index] + disp8 + [EBP]
    10 [scaled index] + disp32 + [EBP]

    例:88 84 48 78 56 34 12

    Opcode:88

    指令格式:MOV Eb, Gb

    ModR/M:84

    Mod:10 Reg/Opcode:000 //使用0號寄存器AL R/M:100 //使用SIB字段

    [--][--]:查詢SIB字段

    SIB:48

    Scale:01 Index:001 //Scale與Index結合指向[ECX*2] Base:000 //使用0號寄存器EAX

    因此,字節碼88 84 48對應的指令為MOV BYTE PTR DS:[EAX+ECX*2+0x12345678], AL

    例:89 84 84 78 56 34 12

    Opcode:89

    指令格式:MOV Ev, Gv

    ModR/M:84

    Mod:10 Reg/Opcode:000 //使用0號寄存器AL R/M:100 //使用SIB字段

    [--][--]:查詢SIB字段

    SIB:84

    Scale:10 Index:001 //Scale與Index結合指向[ECX*2] Base:000 //使用0號寄存器EAX


    因此,字節碼88 84 48對應的指令為MOV DWORD PTR DS:[ESP+EAX*4+0x12345678], EAX

    Opcode Extension Tables

    描述:當操作系統遇到諸如0x80這樣的Opcode時,其指令序列為Eb, Ib,并無指明Opcode

    思考:CPU如何知道Opcode是什么?
    答案:查詢Opcode Extension Tables

    例:80 65 08 FF


    ModR/M:65

    Mod:01 Reg/Opcode:100 //此時不再指向寄存器,用這個值去查Opcode Extension Tables R/M:101 //Mod與R/M結合指向[EBP]+disp8


    因此,字節碼80 65 08 FF對應的指令為AND BYTE PTR SS:[EBP+0x8], 0xFF

    Instruction Prefixs

    描述:指令前綴

    段前綴

    描述
    1)在早期8086CPU尋址范圍較小,Intel采用段寄存器*16+偏移的方式尋址
    2)后來80386CPU擴大了尋址范圍,段寄存器便被用作了其它用途,不參與尋址
    3)但是類似DS:[]這種格式被保留了下來
    4)實際上操作碼已經決定了尋址時使用哪個段寄存器作為基址,不需要其他字節描述

    注意
    1)如果沒有特別說明,[]前為DS,即DS:[]
    2)若是像PUSH和POP指令,以及其它在[]中使用ESP/EBP的指令,默認前綴為SS
    3)在[Base+Index*2Scale+I]中,以Base作為判斷條件,沒有特別說明,默認前綴為DS
    4)如果Base為ESP/EBP,默認前綴為SS
    5)EIP取指令時默認前綴為CS
    6)如果指令加段寄存器前綴,則該條指令一律用這個段; 如果加多個段寄存器前綴,默認只看Opcode前面那個

    默認值

    CS:2E SS:36 DS:3E ES:26 FS:64 GS:65

    操作指令前綴:修改地址默認長度

    描述:在無指令前綴的Opcode中,B0表示MOV AL, Ib,B8表示MOV EAX, Id,但卻不存在MOV AX, I這樣的Opcode,這是因為intel使用指令前綴完成這件事情

    :0x66
    作用:將操作數改為16位模式

    50 PUSH EAX 66:50 PUSH AX

    操作指令前綴:修改默認尋址方式

    :0x67
    作用:將操作數改為16位模式

    88 01 MOV BYTE PTR DS:[ECX], AL 67:8801 MOV BYTE PTR DS:[BX+DI], AL

    總結

    以上是生活随笔為你收集整理的硬编码学习笔记(二)—— 经典变长指令的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。