[心得] x86 machine code
從來沒想過我會學習 machine code, 而且 x86 machine code 實在太複雜, 花了很多心
力才有點進展。本來直接拿起 intel 那令人害怕的手冊硬 K, 果然不行, 有看沒有懂,
再看 ref 3, 還是看不懂。而在閱讀了 ref 1, 2 後, 我如獲至寶, 看懂之後再翻閱
ref 3, 終於有了進展。當能看懂時, 心中的興奮之情, 恐怕只有和我一樣在 machine
code 裡頭掙扎的同好才能理解。
不過 x86 machine code 實在太複雜, 我並沒能搞懂所有格式。
為什麼要研究 machine code 呢?因為要改寫執行檔的位址, 做類似 dynamic
loader/linker 的事情, 會看這篇文章的朋友, 難道你對於 dynamic loader/linker 的
原理沒有興趣嗎?不會想個方法來實驗這件事情嗎?Binary Hacks--駭客秘傳技巧一百招
#72 就在談這個。
讓我們從 intel memory address 開始。intel 著名的 segmentation memory address,
將記憶體位址分為 segment part, offset part, 本文章重點擺在 offset part。而台灣
翻譯的基底/索引定址法 (中國的翻譯則是 ...) 則為 base/index。
offset part 有三個欄位:
base register
index register multiplied 1, 2, 4, 8 (1, 2, 4, 8 被稱為 scale factor)
displacement
base + index * scale + displacement = offset part
ex:
at&t syntax add 0x12345678(%eax, %esi, 4), %esi
intel syntax add esi, [eax+esi*4+0x12345678]
本篇文章大量參考 Programming THE 80386 (instruction encoding - p59):
( http://goo.gl/jr50sq )
這是 1987 年的書 (我寫這篇文章的時間是 20130612), 在電腦界這麼快速更新的時代,
照理說應該是過期的書籍, 不過由於相容性的緣故, 裡頭提到的東西到現在都還是可以用
的, 而且簡單不少 (也沒有 64 bit mode), intel 手冊已經變得又厚又硬難以閱讀, 而
這本書講的比較好理解。有些術語和最新的 intel 手冊有些不同, 不過不影響理解。
之前在閱讀 IBM 80X86 組合語言實務 ( http://goo.gl/Tmr1Pp )被其複雜的定址模式搞
得我好亂, 現在一次把它搞懂。這些複雜的 address mode 是針對 offset part 而來,
大概就是 base register 和 index register mode 這兩種比較複雜。而 16 bit 和 32
bit 又有點不同, 64 bit 沒研究, 就不提了。
16 bit 和 32 bit 可用來當 base/index register 的暫存器有些不同。為什麼呢?讀懂
machine code 就可以回答這問題。
x86 machine code 順序, 後面的數字是 byte 數目:
prefix 0-4
opcode 1-2
modrm 0-2
displacement 0-4
immediate 0-4
這是這本書的解釋, 和目前的 intel 手冊有些不同, 目前的 intel 手冊把 modrm 分為
modrm + sib, 不過沒關係, 原則都是一樣的。我建議先看過 ref 1, ref 2 再看這篇,
如果真的沒時間至少也要看過 ref 2, 因為他們提到的東西, 我不會特別說明, 請花點時
間看, 若你真想理解這玩意, 應該有覺悟要佔去你不少休閒時間。
address_mode.S
1 # practice x86 machine code
2 .code16
3 #.code32
4 .text
5 .global begin
6 begin:
7 add (%bx), %ax
看看 L7 的組語, 這使用了 base register address mode。
objdump -d -m i8086 address_mode.elf
1 descent@w-linux:x86_machine_code$ objdump -d -m i8086 address_mode.elf
2
3 address_mode.elf: file format elf32-i386
4
5
6 Disassembly of section .text:
7
8 00000100 <_text>:
9 100: 03 07 add (%bx),%ax
由於 intel cpu 有 16/32/64 bit mode, 所以我們得選擇要讓組譯器用那種 bit mode
來翻譯出 machine code, 這個例子是 16 bit (ref address_mode.S L2, L3)。
03 07 是 machine code, 對應到 opcode modrm 這兩欄, 沒有 prefix, displacement,
immediate 這些部份。
來看看 add 的 opcode:
http://css.csail.mit.edu/6.858/2011/readings/i386/ADD.htm (
http://goo.gl/onPA8d )
有好幾個, 看以下這個:
03 /r ADD r16,r/m16 2/6 Add r/m word to word register
clock 那欄我看不懂, 有請大大解惑。
所以 03 是 opcode, 03 搞定, 那 07 是什麼?
07 是 modrm 這欄, 再細分解為 2:3:3 欄位,
0000 0111 -> 00 000 111
mod: 00
reg: 000
r/m: 111
把 mod, r/m 拿來查表。
mod = 00 時的對照表 (16 bit)
Effective Addressr/m
[BX+SI] 000
[BX+DI] 001
[BP+SI] 010
[BP+DI] 011
[SI] 100
[DI] 101
disp16 110
[BX] 111
得到 [BX], 這是 base register address mode
reg: 000 代表 ax register
register table
REGRegister
000EAX/AX
001ECX/CX
010EDX/DX
011EBX/BX
100ESP/SP
101EBP/BP
110ESI/SI
111EDI/DI
得到 add ax, [bx] (intel syntax), 恭喜, 終於看懂 machine code 了。但是要從
add ax, [bx] 得到 03 07 就比較難了。
這在 intel 術語稱為: one-byte address mode encoding。
這篇好像有點長了, 不過打鐵趁熱, 來看看 prefix 的例子。
address_mode1.S
1 # practice x86 machine code
2 .code16
3 #.code32
4 .text
5 .global begin
6 begin:
7 add (%bx), %eax
和 address_mode.S 的差別僅在 %eax, %ax 改成 %eax。我一直被 16 bit 程式碼可以使
用 32 bit register 所疑惑, 這樣的程式碼倒底是 16 bit 還是 32 bit? 當然是 16
bit, 那你和我覺得疑惑可以使用 32 bit register 嗎?讓我們透過 prefix 解除這疑惑
。
objdump -d -m i8086 address_mode.elf
1 descent@w-linux:x86_machine_code$ objdump -d -m i8086 address_mode.elf
2
3 address_mode.elf: file format elf32-i386
4
5
6 Disassembly of section .text:
7
8 00000100 <_text>:
9 100: 66 03 07 add (%bx),%eax
machine code 則多了一個 66, 這就是 prefix, 用來切換 operand size, 這裡的例子是
從 16 bit 切換成 32 bit, 本程式執行在 16 bit 下, 而 %eax 是 32 bit operand, 所
以要加上 prefix 0x66, 就這麼簡單。
想想看:
什麼是 32 bit 執行環境?
A: ...
若在 32 bit 執行環境執行這個 machine code 又是什麼意思?
A:
.code32
.text
.global begin
begin:
add (%edi), %ax
很有意思吧, x86 就是這麼討厭又讓人喜愛。
好用的組譯器:http://radare.org/y/?p=examples&f=rasm ( http://goo.gl/7m3UXy )
玩 machine code 的朋友一定要試試。
某聚會上我的分享, 就是以這篇為主。
ref:
x86/x64 指令幕(适用于 AMD/Intel):http://www.mouseos.com/x64/index.html (
http://goo.gl/D7kzHb )
OpCode:http://www.luocong.com/learningopcode.htm ( http://goo.gl/4fAo5p )
Programming THE 80386
http://ref.x86asm.net/coder32.html ( http://goo.gl/311CF )
// 本文使用 Blog2BBS 自動將Blog文章轉成縮址的BBS純文字 http://goo.gl/TZ4E17 //
原文 blog
descent-incoming.blogspot.tw/2013/06/x86-machine-code-0-base-register.html
--
※ 發信站: 批踢踢實業坊(ptt.cc), 來自: 58.114.150.244
※ 文章網址: http://www.ptt.cc/bbs/ASM/M.1399549919.A.C6F.html
推
05/08 22:53, , 1F
05/08 22:53, 1F
推
05/09 12:05, , 2F
05/09 12:05, 2F
http://www.luocong.com/learningopcode/index.htm
這就應該沒問題, 是純 html 網頁
推
05/09 21:38, , 3F
05/09 21:38, 3F
推
05/10 01:39, , 4F
05/10 01:39, 4F
※ 編輯: descent (111.184.191.166), 05/10/2014 22:04:00
推
09/24 04:53, , 5F
09/24 04:53, 5F
ASM 近期熱門文章
PTT數位生活區 即時熱門文章
23
69