X86指令編碼內幕 --- 指令格式
在序言裡的例子裡:
mov dword ptr es:[eax + ecx * 8 + 0x11223344], 0x12345678 |
這裡稍作修改:將記憶體運算元 operand size 的指示符 word ptr 改回 dword ptr,使得指令的 operand size 是 32 位。
這是個具有典型指令編碼意義的指令,它的 encodes(機器編碼)是:26 c7 84 c8 44 33 22 11 78 56 34 12 (共12個位元組)。
go ahead~
1. 編碼序列
如上圖所示:這是 x86/x64 體系的 General-Pupose Instruction(通用體系指令)的編碼格式,記住這個編碼序列很重要,這是解析指令編碼的基石。
這個編碼序列組成部分分為:
- Legacy Prefix
- REX prefix
- Opcode
- ModRM
- SIB
- Displacement
- Immediate
按功能組別,可以將這個指令序列分為 4 大部分:Prefix、Opcode、ModRM/SIB 以及 Displace/Immediate
1.1 Prefix(字首)
AMD推出 x86 擴充套件 64 位技術時,增加了一個用於訪問擴充套件的 64 位資料的 REX prefix,而 x86 的 prefix 則變為了指令格式中的 Legacy prefix。
1.1.1 Legacy prefix
在 legacy 的 x86 模式下 REX prefix 是無效的,但是在 x64 的 64 位下 Legacy prefix 是有效的。
1.1.2 REX prefix
在 64 位模式下,由於絕大多數指令的 default operand size(預設運算元大小)是 32 位,為了可以訪問擴充套件的 64 位資料和 64 位地址,x64 指令體系引入了 REX prefix 來實現這一目的。
1.2 Opcode(操作碼)
大多數通用指令的 Opcode 是單位元組,最多是 2 位元組,但是對有些 Float 指令和 SSEx 等 midea 指令來說是 3 個位元組的。opcode 是指令的核心部分,代表指令是用來幹什麼的?怎樣幹?
1.3 ModRM/SIB
ModRM 和 SIB 是用來提供 operands 的定址模式。
1.3.1 ModRM
ModRM 位元組,意為:mod-reg-r/m 按 2-3-3 比例劃分位元組。
ModRM.mod 是提供定址模式, ModRM.reg 用來提供暫存器 ID,ModRM.r/m 提供 register 或 memory 的 ID
1.3.2 SIB
SIB 意即:Sacle-Index-Base 也是按 2-3-3 比例劃分位元組。
這兩個位元組用來為 memory 運算元提供 base, index 以及 scale
1.4 Disp/Imme
displacement 與 immediate 直接嵌在指令編碼中。
1.4.1 displacement
displacemnt 需要 ModRM 甚至 SIB 提供定址, displacement 最大為 4 個位元組 32 位。
1.4.2 immediate
immediate 部分大多數情況下不需要 ModRM 位元組提供定址,在一些指令還是需要 ModRM 進行定址。
immediate 最大可為 8 個位元組,在 x64 的 64 位下的某些情況才會有的。
注意:
displacement 和 immediate 的兩種情況:
★ 符號數(signed)
在這種情形下:進行運算時,是符號數。
當小於目標 operands 位數時,displacement 和 immediate 都有符號擴充套件的行為,擴充套件到目標運算元的位數。
實際上: (1)當指令的 operand size 是 z 屬性時,如果 immediate 是小於 effective operand size 的,immediate 會進行 sign-extended 行為。 (2)同樣 operand size 是 b 屬性的,如果 immediate 是小於 effective operand size 的,immediate 也會進行 sign-extended 行為。 (3)當指令的 displacement size 小於 address size 的,displacement 會進行 sign-extended 行為。 |
★ 無符號數(unsigned)
在這種情況下,displacement 是一個絕對地址值,immediate 是一個無符號立即數值。
如:mov eax, dword ptr [0x11223344] 或 mov eax, 0x12345678
本質上: ★ 當地址形式中無 base 暫存器時,雖然它是絕對值形式,實際上它仍是基於 segment base 地址。 |
因此,只有 immediate 才具有的 unsigned 的時候。
對照上面的 encode 來看:
26 c7 84 c8 44 33 22 11 78 56 34 12
(1) 26 是 legacy prefix,這是 segment-override prefix,指明是 ES 段選擇子
(2) c7 是 Opcode,表明這個指令是 mov reg/mem, imme
(3) 84 是 ModRm,即:10-000-100。
(4) c8 是 SIB,即:11-001-000
(5) 44332211 是 32 位 displacement 值
(6) 78563412 是 32 位 immediate 值
2、指令長度
上圖中顯示,指令長度最長是 15 個位元組,在什麼時候達到飽和的 15 個位元組呢?
2.1 什麼情況下達到飽和的 15 bytes
答案是如下類似指令:
lock add dword ptr es:[eax+ecx*8+0x11223344], 0x12345678 |
當在 16 位程式碼下,這條指令將達到飽和的 15 個位元組長度。
注意:僅在 16 位下,這條指令的編碼是:
26 66 67 F0 81 84 C8 44 33 22 11 78 56 34 12 (正好 15 個位元組)
這個編碼的具體含義:
26 66 67 F0: 這 4 個位元組是 prefix,這 4 個位元組達到了飽和的 prefix 狀態。
- 26 是 ES segment register
- 66 是 operand-size override
- 67 是 address-size override
- F0 是 Lock prefix
C7:Opcode
84:ModRM
C8:SIB
44 33 22 11:displacement
78 56 34 12:immediate
有沒有超過 15 個位元組的指令編碼,答案是:沒有! 那麼在 64 位下呢? 答案同樣是沒有!
2.2 為什麼指令長度最長是 15 位元組?
★ 4 個位元組的 prefix 已經達到飽和度了:
- 1 個位元組用來調整 segment selector registers
- 1 個位元組用來調整 Operand effective size
- 1 個位元組用來調整 Address effective size
- 還有 1 個位元組用來 lock 匯流排
已經無法再增加 prefix 了。
★ 若是採用 2 個位元組的 Opcode 碼,則定址模式上不會有 mem32, imm32 這種操作法。所以還是採用 1 個位元組的 Opcode,而得到 4 個位元組的立即數。
★ ModRM + SIB:2 個位元組。
★ 4 個位元組的 displacement 值。
★ 4 個位元組的 immediate 值。
這樣每個組成部分都呈飽和狀態,加起來總共 15 個位元組,而只有採用 mem32, imme32 這種定址模式可能會達到飽和狀態。
在 64 位下,若採用 mem, imme 的定址模式,這和 32 位是一致的,所以不會超越 15 個位元組,
2.3 prefix 的限制
prefix 的限制來自 legacy prefix (包括:operand size override、address size override、segment override、repeat prefix 以及 lock prefix)本身之間,
以及與 REX prefix 之間存在衝突:
- 在 64 位下,operand size override
3、 encodes 的位元組序
x86/x64 指令的 encodes 在記憶體中是以 little endian 儲存的,這主要體現在 displacement 和 immediate 部分。
在 encode 序列裡,legacy prefix 在低端,依次往 immediate 部分在高階。
mov dword ptr es:[eax + ecx * 8 + 0x11223344], 0x12345678 |
指令中的 displacement 是 0x11223344,在記憶體的 little endian 序列是:44 33 22 11
immediate 是 0x12345678 在記憶體的 lttle endian 序列是:78 56 34 12
相關推薦
X86指令編碼內幕 --- 指令格式
在序言裡的例子裡: mov dword ptr es:[eax + ecx * 8 + 0x11223344], 0x12345678 這裡稍作修改:將記憶體運算元 operand size 的指示符 word ptr 改回 dword ptr,使得指令的 opera
X86指令編碼內幕 --- 指令 Opcode 碼
指令 Opcode 碼 x86 指令編碼的核心是:Opcode、ModRM 以及 SIB。Opcode 提供指令的操作碼,ModRM 及 SIB 提供運算元的定址模式。 指令編碼設計模式是:Opcode 的設計要考慮兼顧 ModRM。ModRM 要服務於 Opcode,S
X86指令編碼內幕 --- ModRM 定址模式
ModRM 定址模式 在 x86/x64 指令集的世界裡: Opcode 對指令提供操作碼,ModRM 最主要作用是對指令的 operands 提供定址,另一個作用是對 Opcode 進行補充,而 SIB 則是對 ModRM 進行補充定址 有兩種情況下是無需用 Mo
從編譯器源代碼中提取ARMv8的指令編碼
med constant ray 結構 any exce clas 標識 變量 2012年11月份的資料,之前ARMv8手冊還沒公布,我想辦法從編譯器的binutils中提取出了全部ARMv8指令的二進制編碼,之前不能隨便發,如今相當於解禁了^_^。
《深入理解計算機系統》練習題3.13-3.16 set指令 跳轉指令編碼
文章目錄 set指令訪問條件碼 3.13 跳轉指令編碼 3.15 cmp指令運算元順序 3.16 3.21 set指令訪問條件碼 SET指令根據條件碼或者條件碼的組合來將一個位元組設定為0或1(所以如果s
Atitit 計算機系統結構 計算機系統結構 Cpu 儲存 cache 指令系統 目錄 Line 56: 第2章指令系統設計 指令格式 定址方式 1 Line 64: 第3章CPU及其實現
Atitit 計算機系統結構 計算機系統結構 Cpu 儲存 cache 指令系統 目錄 Line 56: 第2章指令系統設計 指令格式 定址方式 1 Line 64: 第3章CPU及其實
【計組】-- 指令系統(1) : 指令格式
概緒 參考書目:《計算機組成原理》(第三版) 蔣本珊 編著 指令、指令系統是計算機中一個最基本的概念。指令是指示計算機執行某些操作的命令,一臺計算機的所有指令的集合構成該機
原子操作與 x86 上的 lock 指令字首
原子操作是不可分割的操作,在執行完畢時它不會被任何事件中斷。在單處理器系統(UniProcessor,簡稱 UP)中,能夠在單條指令中完成的操作都可以認為是原子操作,因為中斷只能發生在指令與指令之間。 在多處理器系統(Symmetric Multi-Processor,簡稱
jsp用靜態指令編碼問題
首先我們有時候儲存jsp會報錯說ISO-8859-1儲存失敗這是ISO-8859-1不能儲存中文的原因首先要去 Window-->General-->Content Types-->
python中關於編碼,json格式的中文輸出顯示
pri 整體 pytho src repr 接口 ensure 輸出 unicode 但我們用requests請求一個返回json的接口時候, 語法是 result=requests.post(url,data).content print type(result),re
JSP中的編譯指令和動作指令的差別
font class 編譯 執行 gb2 ron 消息 腳本 con JSP中的編譯指令和動作指令的差別 1、編譯指令是通知Servlet引擎的處理消息。而動作指令僅僅是執行時的腳本動作 2、編譯指令是在將JSP編譯成Servlet時起作用,而動作指令可替換成J
ARM指令集—SWP指令
而且 post margin {} 這樣的 有效 介紹 back swp ARM指令集—SWP指令 SWP和SWPB是ARM指令集中對存儲單元的原子操作。即對存儲單元的一次讀和一次不可被切割。SWP和SWPB分別完畢存儲器和寄存器之間 一個字(
Velocity(4)——引入指令和#Parse 指令
層次 必須 dep 屬性 mil das eight mar height #Include和#Parse都是用於將本地文件引入當前文件的指令,而且被引入的文件必須位於TEMPLATE_ROOT。這兩者之間有一些區別。 #Include 被#Include引入的文件,其
jsp筆記2(編譯指令與動作指令)
getpara html 丟失 另一個 value 默認 extend servlet encoding 一、jsp的編譯指令是通知jsp引擎的消息,不會生成輸出。 jsp的3個編譯指令: page:針對當前頁面的指令 include:包含另一個頁面的指令
字符編碼,時間格式轉換
encode codes decode 格式 unicode轉化 instr hello AI 普通 普通字符串可以用多種方式編碼成Unicode字符串,具體要看你究竟選擇了哪種編碼:unicodestring = u"Hello world" # 將Unicode轉
向量指令和標量指令
actor 基本 .get 對象 oid dom nod 文件的 imp 向量指令和標量指令:有些大型機和巨型機 設置功能齊全的向量運算指令系統。 向量指令的基本操作對象是向量,即有序排列的一組數。 若指令為向量操作,則由指令確定向量操作數的地址(主存儲器起始地址或向量寄
匯編語言指令是機器指令的符號化
lec 匯編 系統 close rac finall 缺點 stream port 匯編語言指令是機器指令的符號化 ,與機器指令存在著直接的對應關系,所以匯編語言同樣存在著難學難用、容易出錯、維護困難等缺點。 但是匯編語言也有自己的優點:可直接訪問系統接口,匯編程序翻譯成
CE的LVD指令,EMC指令都測試些什麽
保護套 震動 電氣 溢出 試驗 防火 封裝 天線 電路 歐盟CE認證的LVD指令、EMC指令檢測的具體項目: 一、安全實驗(LVD): 1.工作電壓 2.故障試驗 3.撞擊實驗 4.震動實驗 5.沖擊試驗 6.電氣間隙、爬電距離和絕緣穿透距離 7.插頭實驗 8.保護連接導體
《組合語言》實驗二——用機器指令和彙編指令程式設計
.title { background-color: #4682B4 } 實驗任務一:使用debug將下面的程式寫入記憶體,逐條執行,根據指令執行後的實際執行情況填空。 前提說明:為便於驗證實驗結果,對實驗任務一做了2點調整: ①在使用a命令輸入指令除錯前,使用e命令將記憶體單元0021:0~002
more指令和less指令使用的區別
more和less都是可以一頁一頁的翻動 more翻頁的時候,顯示有百分比在最下一行 less沒有 more可以用來查詢 空白鍵 (space):代表向下翻一頁;Enter :代表向下翻『一行』;/字串 :代表在這個顯示的內容當中,向下搜尋『字串』這個關鍵字;q :代表立刻離開 more ,不再顯示該