顯示具有 x86_machine_code 標籤的文章。 顯示所有文章
顯示具有 x86_machine_code 標籤的文章。 顯示所有文章

2018年2月23日 星期五

x86 machine code 初探 (8) - mov +rd

我邁進到組譯器階段了, 第一個難關便是如何產生 x86 machine code, 連最簡單的 mov 都難倒我。人腦找資料看懂這些數字都不容易了, 而要讓電腦將組合語言轉成 machine code 更讓我不知所措。

env:
x86 32bit mode

list 1.
b8 01 00 00 00          mov    $0x1,%eax
bb 01 00 00 00          mov    $0x1,%ebx

天阿! 這魔法般的數字是怎麼來的。

x86 Instruction Set Reference mov 找到這些規則。

list 2.
1 B8+rd  MOV r32,imm32   Move imm32 to r32.
2 C7/0 MOV r/m32,imm32 Move imm32 to r/m32.

mov 有很多格式, list 1. 的指令是對應到 list 2. rd 這種格式, 但我覺得第二種格式應該也可以。

table 1. register table
REGRegister
000EAX/AX
001ECX/CX
010EDX/DX
011EBX/BX
100ESP/SP
101EBP/BP
110ESI/SI
111EDI/DI

b8, bb 的數字是怎麼來的呢?

b8 => 1011 1000
紅色的 000 就是 table 1 要填入的 register value, eax 是 000, 所以得到 => 1011 1000 (b8)
ebx 是 101, 所以得到 => 1011 1101 (bb)

後面的 01000000 就是 $0x1。

2013年12月11日 星期三

x86 machine code 初探 (7) - jmp

Orange's 一個作業系統的實現 (p 3-25) 從保護模式回到真實模式的 jmp 指令改寫, 作者用這招從 dos 切到保護模式後再切回到真實模式。厲害!若只看 intel datasheet, 沒看過程式碼, 我自己能想到嗎?

.code16
jmp     $0, $LABEL_REAL_ENTRY      # 段位址會在程序開始處被設置成正確的值
 6ed:   ea bd 03 00 00          ljmp   $0x0,$0x3bd

JMP ptr16:16

ea 查這個表
http://pdos.csail.mit.edu/6.828/2006/readings/i386/appa.htm
-> Jv, Ap, Jb 應該是 Ap。

A : jmp 後面的是位址
p: 32 or 48 bit pointer

ptr16:16 表示這位址由兩個部份組成 segment + offset,
藍色的 00 00 是 segment part, 在真實模式和保護模式有不同的意思, 而程式需要的是真實模式, 所以將這個 segment 改成真實模式下需要的值。

紅色的bd 03是 offset,

L1便是在修改 L3 的藍色部份 (segment), 填入當時的 %ax (載入這個 .com 時, 還在真實模式下的 %ax), 用來返回真實模式。哇! 我到現在才懂 (20130923), 之前看不懂, 只是照抄。

1 movw %ax, (LABEL_GO_BACK_TO_REAL+3)
2 LABEL_GO_BACK_TO_REAL:
3    jmp     $0, $LABEL_REAL_ENTRY   

這篇的文字很少, 不過金字塔知識門檻很高, 並且還要查閱 intel 手冊才能完成這篇。

2013年9月26日 星期四

x86 machine code 初探 (6) - displacement-only

mod reg r/m 當 r/m 是 101 時, 也是例外。這表示 displacement only。

ex1:
address_mode.S
 1 # practice x86 machine code
 2 #.code16
 3 .code32
 4 .text
 5 .global begin
 6 begin:
 7   mov val, %esi
 8
 9 val:
10 .int

這個竟然這麼麻煩, 要出動 readelf

readelf -a   address_mode.elf 
Symbol table '.symtab' contains 14 entries:
   Num:    Value  Size Type    Bind   Vis      Ndx Name
     0: 00000000     0 NOTYPE  LOCAL  DEFAULT  UND 
     1: 00000100     0 SECTION LOCAL  DEFAULT    1 
     2: 00000000     0 SECTION LOCAL  DEFAULT    2 
     3: 00000000     0 SECTION LOCAL  DEFAULT    3 
     4: 00000000     0 SECTION LOCAL  DEFAULT    4 
     5: 00000000     0 SECTION LOCAL  DEFAULT    5 
     6: 00000000     0 FILE    LOCAL  DEFAULT  ABS address_mode.o
     7: 00000106     0 NOTYPE  LOCAL  DEFAULT    1 val
     8: 00000000     0 FILE    LOCAL  DEFAULT  ABS 
     9: 00000106     0 NOTYPE  GLOBAL DEFAULT    1 _text_end
    10: 00000100     0 NOTYPE  GLOBAL DEFAULT    1 begin
    11: 00000106     0 NOTYPE  GLOBAL DEFAULT    1 _data_end
    12: 00000100     0 NOTYPE  GLOBAL DEFAULT    1 _text
    13: 00000106     0 NOTYPE  GLOBAL DEFAULT    1 _data

L7 : val 的位址 0x106
objdump -d address_mode.elf
8b 35 06 01 00 00     mov    0x106,%esi

mod reg r/m 35 => 00 110 101
mod, r/m 查表 DS:Disp32
reg 110 => %esi
disp32 => 06 01 00 00 => 00 00 01 06
b8 自己查。

ex2:

address_mode.S
 1 # practice x86 machine code
 2 #.code16
 3 .code32
 4 .text
 5 .global begin
 6 begin:
 7   movb $0x12, val
 8
 9 val:
10 .byte

gcc -m32  -g -Wall -Wextra -Werror -nostdlib -fno-builtin -nostartfiles -nodefaultlibs -fno-exceptions -fno-rtti -fno-stack-protector -c address_mode.S
ld -m elf_i386 -static -Tas.ld -nostdlib --nmagic -o address_mode.elf address_mode.o

objdump
c6 05 07 01 00 00 12  movb   $0x12,0x107


readelf -a   address_mode.elf 

Symbol table '.symtab' contains 14 entries:
   Num:    Value  Size Type    Bind   Vis      Ndx Name
     0: 00000000     0 NOTYPE  LOCAL  DEFAULT  UND 
     1: 00000100     0 SECTION LOCAL  DEFAULT    1 
     2: 00000000     0 SECTION LOCAL  DEFAULT    2 
     3: 00000000     0 SECTION LOCAL  DEFAULT    3 
     4: 00000000     0 SECTION LOCAL  DEFAULT    4 
     5: 00000000     0 SECTION LOCAL  DEFAULT    5 
     6: 00000000     0 FILE    LOCAL  DEFAULT  ABS address_mode.o
     7: 00000107     0 NOTYPE  LOCAL  DEFAULT    1 val
     8: 00000000     0 FILE    LOCAL  DEFAULT  ABS 
     9: 00000107     0 NOTYPE  GLOBAL DEFAULT    1 _text_end
    10: 00000100     0 NOTYPE  GLOBAL DEFAULT    1 begin
    11: 00000107     0 NOTYPE  GLOBAL DEFAULT    1 _data_end
    12: 00000100     0 NOTYPE  GLOBAL DEFAULT    1 _text
    13: 00000107     0 NOTYPE  GLOBAL DEFAULT    1 _data
L7 : val 的位址 0x107

mod reg r/m 05 => 00 000 101
r/m 101

100:    c6 05 07 01 00 00 12     movb   $0x12,0x107
c6 查表 One-Byte Opcode Map Eb, Ib

ref:Intel_64 and IA-32 Architectures Software Developer’s Manual Combined Volumes: 1, 2A, 2B, 2C, 3A, 3B and 3C
page Vol. 2C B-16

mov 指令格式
immediate to memory 1100 011w : mod 000 r/m : immediate data

應該是 Ib

I
Immediate data. The value of the operand is encoded in subsequent bytes of the instruction.

b
Byte (regardless of operand size attribute)

07 01 00 00 : displacement
12 : immediate

2013年9月21日 星期六

x86 machine code 初探 (5) - 兩個 modrm base/index with scale factor address mode

modrm 的 r/m:100 時, 這是一個特殊的記號, 代表下一個 byte 又是一個 modrm, 不過目前被稱為 SIB 欄位。Programming THE 80386 p71 稱這是 two-byte address mode encoding。

address_mode.S
1 # practice x86 machine code
2 #.code16
3 .code32
4 .text
5 .global begin
6 begin:
7   mov 24(%esp,%esi,8), %eax

objdump:
8b 44 f4 18 mov 0x18(%esp,%esi,8),%eax

att syntax: displacement(base, index, scale)

mov
8B  /r   MOV r16,r/m16     2/4           Move r/m word to word register
8B  /r   MOV r32,r/m32     2/4           Move r/m dword to dword register

44 -> mod reg r/m 01 000 100 reg:000 -> %eax
mod 01 表示 8bit displacement(0x18)
r/m 100, 所以下一個也是 modrm (SIB)

f4 -> mod reg r/m 11 110 100 這代表著
scale index base
11    110   100
8     %esi  %esp

若是 mode 10 表示 32 bit displacement。

ex:
8b 84 f4 32 54 76 98     mov    -0x6789abce(%esp,%esi,8),%eax
44 -> 84
od reg r/m 10 000 100

解說完畢。

2013年8月25日 星期日

x86 machine code 初探 (4) - mov immediate

一樣用例子來說明, 這次來解讀 mov immediate, L10 ~ L12:

address_mode.S
 1 # practice x86 machine code
 2 #.code16
 3 .code32
 4 .text
 5 .global begin
 6 begin:
 7 #  add 0x12345678(%eax, %esi, 4), %esi
 8 #  add 0x12(%bx, %si, 2), %si
 9 #  mov  0x1234,%esi 
10   movl  $5, (%ebx)
11   movb  $5, (%ebx)
12   mov  $5, %ebx


objdump -d address_mode.elf
 1 descent@w-linux:x86_machine_code$ objdump -d address_mode.elf 
 2 address_mode.elf:     file format elf32-i386
 3 
 4 
 5 Disassembly of section .text:
 6 
 7 00000100 <_text>:
 8  100:   c7 03 05 00 00 00       movl   $0x5,(%ebx)
 9  106:   c6 03 05                movb   $0x5,(%ebx)
10  109:   bb 05 00 00 00          mov    $0x5,%ebx

ref:
Intel_64 and IA-32 Architectures Software Developer’s Manual Combined Volumes: 1, 2A, 2B, 2C, 3A, 3B and 3C
page
Vol. 2C B-36/B-37

這個表有 non-64 bit 和 64 bit mode 的分別
MOV – Move Data
#0 immediate to register 1100 011w : 11 000 reg : immediate data
#1 immediate to register (alternate encoding) 1011 w reg : immediate data
#2 immediate to memory 1100 011w : mod 000 r/m : immediate data

intel machine code 果然複雜, 越新的手冊內容越多, 密密麻麻的欄位看得令人頭皮發麻。這次來看看 opcode 欄位裡頭的 w bit:

B.1.4 Special Fields
Table B-1 lists bit fields that appear in certain instructions, sometimes within the opcode bytes. All of these fields (except the d bit) occur in the general-purpose instruction formats in Table B-13. Table B-1. Special Fields Within Instruction Encodings

w Specifies if data is byte or full-sized, where full-sized is 16 or 32 bits (see Table B-6)  1   

Table B-6. Encoding of Operand Size (w) Bit
w BitOperand Size When Operand-Size Attribute is 16 Bits Operand Size When Operand-Size Attribute is 32 Bits
08 Bits8 Bits
1 16 Bits 32 Bits

有了這兩個資訊, 我們就可以解讀 mov 的 machine code。

先來看 address_mode.S L 10:
movl $0x5,(%ebx)
c7 03 05 00 00 00

c7 -> Ev,Iv 這裡應該是指 Ev
03 is modrm
modrm -> 2:3:3
mod: 00
reg: 000
r/m: 011
符合 #2 1100 011w : mode 000 r/m : imm
所以 05 00 00 00 is imm
w 為 1, 所以 opcode 是 c7。

mod:00 r/m:011 => [ebx]

再來看看
11   movb  $5, (%ebx)
machine code: c6 03 05
對照這些表格資料, 應該可以知道為什麼是 opcde: c6, imm: 05 (提示: w=0)

再看
12   mov  $5, %ebx
machine code: bb 05 00 00 00
這次要對照 #1
1011
w: 1
reg: 011 -> ebx
imm: 05 00 00 00
所以得到 bb 05 00 00 00

真辛苦, 又完成一次人工解讀。

2013年7月6日 星期六

x86 machine code 初探 (3) - opcode extension

FF 15 D4 81 DF 00 這是 http://www.mouseos.com/x64/preface.html 的例子, 我一直看不懂, 不過我現在搞清楚了。

call dword ptr [00DF81D4h]

descent@w-linux:x86_machine_code$ rasm2 "call dword ptr [00DF81D4h]"
ff15d481df00
descent@w-linux:x86_machine_code$ man rasm2
descent@w-linux:x86_machine_code$ rasm2 -s att "call (0x00DF81D4)"
e8cf81df00
descent@w-linux:x86_machine_code$ rasm2 -d "FF 15 D4 81 DF 00"
call dword [0xdf81d4]

att syntax:
ff 15 d4 81 df 00        call   *0xdf81d4


ModRM: 15
mod: 00
reg: 010
r/m: 101

mod: 00
r/m: 101
-> disp32

ff 查 opcode map 得到 group5 (Grp5), 再根據 reg: 010 查 opcode extensions group 表得到 call (Ev)

E A modR/M byte follows the opcode and specifies the operand. The operand is either a general register or a memory address. If it is a memory address, the address is computed from a segment register and any of the following values: a base register, an index register, a scaling factor, a displacement.

v Word or double word, depending on operand size attribute.


One-Byte Opcode Map

0         1         2         3         4         5         6        7        8         9         A         B         C         D         E        F
 +-----------------------------------------------------------+--------+--------+-----------------------------------------------------------+--------+--------+
 |                              ADD                          |  PUSH  |   POP  |                             OR                            |  PUSH  | 2-byte |
0|---------+---------+---------+---------+---------+---------+        |        +---------+---------+---------+---------+---------+---------+        |        |
 |  Eb,Gb  |  Ev,Gv  |  Gb,Eb  |  Gv,Ev  |  AL,Ib  | eAX,Iv  |   ES   |   ES   |  Eb,Gb  |  Ev,Gv  |  Gb,Eb  |  Gv,Ev  |  AL,Ib  | eAX,Iv  |   CS   | escape |
 +---------+---------+---------+---------+---------+---------+--------+--------+---------+---------+---------+---------+---------+---------+--------+--------+
 |                              ADC                          |  PUSH  |   POP  |                            SBB                            |  PUSH  |  POP   |
1|---------+---------+---------+---------+---------+---------+        |        +---------+---------+---------+---------+---------+---------+        |        |
 |  Eb,Gb  |  Ev,Gv  |  Gb,Eb  |  Gv,Ev  |  AL,Ib  | eAX,Iv  |   SS   |   SS   |  Eb,Gb  |  Ev,Gv  |  Gb,Eb  |  Gv,Ev  |  AL,Ib  | eAX,Iv  |   DS   |   DS   |
 +---------+---------+---------+---------+---------+---------+--------+--------+---------+---------+---------+---------+---------+---------+--------+--------+
 |                              AND                          |  SEG   |        |                            SUB                            |  SEG   |        |
2|---------+---------+---------+---------+---------+---------+        |   DAA  +---------+---------+---------+---------+---------+---------+        |  DAS   |
 |  Eb,Gb  |  Ev,Gv  |  Gb,Eb  |  Gv,Ev  |  AL,Ib  | eAX,Iv  |  =ES   |        |  Eb,Gb  |  Ev,Gv  |  Gb,Eb  |  Gv,Ev  |  AL,Ib  | eAX,Iv  |  =CS   |        |
 +---------+---------+---------+---------+---------+---------+--------+--------+---------+---------+---------+---------+---------+---------+--------+--------+
 |                              XOR                          |  SEG   |        |                            CMP                            |  SEG   |        |
3|---------+---------+---------+---------+---------+---------+        |   AAA  +---------+---------+---------+---------+---------+---------+        |  AAS   |
 |  Eb,Gb  |  Ev,Gv  |  Gb,Eb  |  Gv,Ev  |  AL,Ib  | eAX,Iv  |  =SS   |        |  Eb,Gb  |  Ev,Gv  |  Gb,Eb  |  Gv,Ev  |  AL,Ib  | eAX,Iv  |  =CS   |        |
 +---------+---------+---------+---------+---------+---------+--------+--------+---------+---------+---------+---------+---------+---------+--------+--------+
 |                               INC general register                          |                              DEC general register                           |
4|---------+---------+---------+---------+---------+---------+--------+--------+---------+---------+---------+---------+---------+---------+--------+--------+
 |   eAX   |   eCX   |   eDX   |   eBX   |   eSP   |   eBP   |  eSI   |  eDI   |   eAX   |   eCX   |   eDX   |   eBX   |   eSP   |   eBP   |   eSI  |  eDI   |
 +---------+---------+---------+---------+---------+---------+--------+--------+---------+---------+---------+---------+---------+---------+--------+--------+
 |                               PUSH general register                         |                          POP into general register                          |
5|---------+---------+---------+---------+---------+---------+--------+--------+---------+---------+---------+---------+---------+---------+--------+--------+
 |   eAX   |   eCX   |   eDX   |   eBX   |   eSP   |   eBP   |  eSI   |  eDI   |   eAX   |   eCX   |   eDX   |   eBX   |   eSP   |   eBP   |  eSI   |  eDI   |
 +---------+---------+---------+---------+---------+---------+--------+--------+---------+---------+---------+---------+---------+---------+--------+--------+
 |         |         |  BOUND  |  ARPL   |   SEG   |   SEG   | Operand| Address|  PUSH   |  IMUL   |  PUSH   |  IMUL   |  INSB   | INSW/D  | OUTSB  |OUTSW/D |
6|  PUSHA  |  POPA   |         |         |         |         |        |        |         |         |         |         |         |         |        |        |
 |         |         |  Gv,Ma  |  Ew,Rw  |   =FS   |   =GS   |  Size  |  Size  |   Ib    | GvEvIv  |   Ib    | GvEvIv  |  Yb,DX  |  Yb,DX  | Dx,Xb  | DX,Xv  |
 +---------+---------+---------+---------+---------+---------+--------+--------+---------+---------+---------+---------+---------+---------+--------+--------+
 |                    Short displacement jump of condition (Jb)                |                   Short-displacement jump on condition(Jb)                  |
7|---------+---------+---------+---------+---------+---------+--------+--------+---------+---------+---------+---------+---------+---------+--------+--------+
 |   JO    |   JNO   |   JB    |   JNB   |   JZ    |  JNZ    |   JBE  |  JNBE  |   JS    |   JNS   |   JP    |   JNP   |   JL    |  JNL    |  JLE   |  JNLE  |
 +---------+---------+---------+---------+---------+---------+--------+--------+---------+---------+---------+---------+---------+---------+--------+--------+
 |  Immediate Grpl   |         |  Grpl   |       TEST        |      XCHG       |                 MOV                   |   MOV   |   LEA   |  MOV   |  POP   |
8|---------+---------+         |         +---------+---------+--------+--------+---------+---------+---------+---------+         |         |        |        |
 |  Eb,Ib  |  Ev,Iv  |         |  Ev,Iv  |  Eb,Gb  |  Ev,Gv  |  Eb,Gb |  Ev,Gv |  Eb,Gb  |  Ev,Gv  |  Gb,Eb  |  Gv,Ev  |  Ew,Sw  |  Gv,M   |  Sw,Ew |   Ev   |
 +---------+---------+---------+---------+---------+---------+--------+--------+---------+---------+---------+---------+---------+---------+--------+--------+
 |         |              XCHG word or double-word register with eAX           |         |         |  CALL   |         |  PUSHF  |  POPF   |        |        |
9|   NOP   +---------+---------+---------+---------+---------+--------+--------+   CBW   |   CWD   |         |  WAIT   |         |         |  SAHF  |  LAHF  |
 |         |   eCX   |   eDX   |   eBX   |   eSP   |   eBP   |  eSI   |  eDI   |         |         |   Ap    |         |   Fv    |   Fv    |        |        |
 +---------+---------+---------+---------+---------+---------+--------+--------+---------+---------+---------+---------+---------+---------+--------+--------+
 |                  MOV                  |  MOVSB  | MOVSW/D | CMPSB  |CMPSW/D |       TEST        |  STOSB  | STOSW/D |  LODSB  | LODSW/D | SCASB  |SCASW/D |
A|---------+---------+---------+---------+         |         |        |        +---------+---------+         |         |         |         |        |        |
 |  AL,Ob  |  eAX,Ov |  Ob,AL  |  Ov,eAX |  Xb,Yb  |  Xv,Yv  |  Xb,Yb |  Xv,Yv |  AL,Ib  | eAX,Iv  |  Yb,AL  |  Yv,eAX |  AL,Xb  | eAX,Xv  |  AL,Xb |eAX,Xv  |
 +---------+---------+---------+---------+---------+---------+--------+--------+---------+---------+---------+---------+---------+---------+--------+--------+
 |                       MOV immediate byte into byte register                 |        MOV immediate word or double into word or double register            |
B|---------+---------+---------+---------+---------+---------+--------+--------+---------+---------+---------+---------+---------+---------+--------+--------+
 |    AL   |   CL    |   DL    |   BL    |   AH    |   CH    |   DH   |   BH   |   eAX   |   eCX   |   eDX   |   eBX   |   eSP   |   eBP   |   eSI  |  eDI   |
 +---------+---------+---------+---------+---------+---------+--------+--------+---------+---------+---------+---------+---------+---------+--------+--------+
 |    Shift Grp2     |      RET near     |   LES   |   LDS   |       MOV       |  ENTER  |         |      RET far      |  INT    |  INT    |        |        |
C|---------+---------+---------+---------+         |         +--------+--------+         |  LEAVE  +---------+---------+         |         |  INTO  |  IRET  |
 |  Eb,Ib  |  Ev,Iv  |    Iw   |         |  Gv,Mp  |  Gv,Mp  |  Eb,Ib |  Ev,Iv |  Iw,Ib  |         |   Iw    |         |   3     |  Ib     |        |        |
 +---------+---------+---------+---------+---------+---------+--------+--------+---------+---------+---------+---------+---------+---------+--------+--------+
 |               Shift Grp2              |         |         |        |        |                                                                             |
D|---------+---------+---------+---------+   AAM   |   AAD   |        |  XLAT  |                  ESC(Escape to coprocessor instruction set)                 |
 |   Eb,1  |  Ev,1   |  Eb,CL  |  Ev,CL  |         |         |        |        |                                                                             |
 +---------+---------+---------+---------+---------+---------+--------+--------+---------+-----------------------------+-------------------+-----------------+
 | LOOPNE  |  LOOPE  |   LOOP  |  JCXZ   |        IN         |       OUT       |   CALL  |             JNP             |        IN         |       OUT       |
E|         |         |         |         +---------+---------+--------+--------+         +---------+---------+---------+---------+---------+--------+--------+
 |   Jb    |   Jb    |    Jb   |   Jb    |  AL,Ib  | eAX,Ib  |  Ib,AL | Ib,eAX |    Av   |   Jv    |   Ap    |   Jb    |  AL,DX  | eAX,DX  | DX,AL  | DX,eAX |
 +---------+---------+---------+---------+---------+---------+--------+--------+---------+---------+---------+---------+---------+---------+--------+--------+
 |         |         |         |   REP   |         |         |     Unary Grp3  |         |         |         |         |         |         |INC/DEC |Indirct |
F|  LOCK   |         |  REPNE  |         |   HLT   |   CMC   +--------+--------+   CLC   |   STC   |   CLI   |   STI   |   CLD   |   STD   |        |        |
 |         |         |         |  REPE   |         |         |   Eb   |   Ev   |         |         |         |         |         |         |  Grp4  |  Grp5  |
 +---------+---------+---------+---------+---------+---------+--------+--------+---------+---------+---------+---------+---------+---------+--------+--------+


Opcodes determined by bits 5,4,3 of modR/M byte (opcode extensions group)

G                       +-------+-------+-------+
     r                       |  mod  |  nnn  |  R/M  |
     o                       +-------+-------+-------+
     u
     p   000     001     010     011     100     101     110     111
      +-------+-------+-------+-------+-------+-------+-------+-------+
     1|  ADD  |  OR   |  ADC  |  SBB  |  AND  |  SUB  |  XOR  |  CMP  |
      |       |       |       |       |       |       |       |       |
      +-------+-------+-------+-------+-------+-------+-------+-------+
     2|  ROL  |  ROR  |  RCL  |  RCR  |  SHL  |  SHR  |       |  SAR  |
      |       |       |       |       |       |       |       |       |
      +-------+-------+-------+-------+-------+-------+-------+-------+
     3| TEST  |       |  NOT  |  NEG  |  MUL  | IMUL  |  DIV  | IDIV  |
      | Ib/Iv |       |       |       |AL/eAX |AL/eAX |AL/eAX |AL/eAX |
      +-------+-------+-------+-------+-------+-------+-------+-------+
     4|  INC  |  DEC  |       |       |       |       |       |       |
      |  Eb   |  Eb   |       |       |       |       |       |       |
      +-------+-------+-------+-------+-------+-------+-------+-------+
     5|  INC  |  DEC  | CALL  | CALL  |  JMP  |  JMP  | PUSH  |       |
      |  Ev   |  Ev   |  Ev   |  eP   |  Ev   |  Ep   |  Ev   |       |
      +-------+-------+-------+-------+-------+-------+-------+-------+

2013年6月28日 星期五

x86 machine code 初探 (2) - displacement only

intel 手冊我很早就印出來拜讀, 所以我的版本沒有 64 bit 部份, 我大部份的心力都放在 16/32 bit 環境下。若要再研究 64bit, 我可能沒有休閒時間了。

休息也是很重要的, 我並不希望我的人生只有程式碼。嗯!該去騎車了。



這次我們來看看特例的例子:

address_mode.S
1 # practice x86 machine code
3 .code32
4 .text
5 .global begin
6 begin:
7   mov  0x1234,%esi

address_mode.S L7 僅僅使用 displacement 這個欄位。這是把 0x1234 位址的 4 個 byte 複製到 %esi。

objdump -d address_mode.elf
1 descent@w-linux:x86_machine_code$ objdump -d 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: 8b 35 34 12 00 00     mov    0x1234,%esi

來看看 machine code, 8b 就不提了, 應該很簡單。

8b 查這個表
http://pdos.csail.mit.edu/6.828/2006/readings/i386/appa.htm
-> Gv, Ev

E
A modR/M byte follows the opcode and specifies the operand. The operand is either a general register or a memory address. If it is a memory address, the address is computed from a segment register and any of the following values: a base register, an index register, a scaling factor, a displacement.
G
The reg field of the modR/M byte selects a general register; e.g., ADD (00).
v
Word or double word, depending on operand size attribute.

感覺好像是 Ev, word 是 2 byte, double word 是 4 byte。

modrm: 35
mod: 00
reg: 110
r/m: 101

reg: 110 -> esi

mod:00
r/m: 101
結果可不是 ebp base register, 如果是 ebp base register, 那組合語言就是

mov  (%ebp),%esi

不過範例中的組合語言不是這個, 這是一個例外, 很意外嗎?不過還有另外一個例外。
這是表示後面接 displacement。所以 34 12 00 00 就是 0x1234 displacement。

那 mov  (%ebp),%esi 會生成產生什麼樣的 machine code 呢?
8b 75 00                 mov    0x0(%ebp),%esi

modrm: 75
mod: 01
reg: 110 -> esi
r/m: 101

mod:01
r/m: 101
查表 http://pdos.csail.mit.edu/6.828/2006/readings/i386/s17_02.htm 得到 -> disp8[ebp]

00 是 8bit displacement, 所以還是可以使用 ebp 當 base register, 只不過 displacement 要為 0, 比其他的 base register 多出一個 byte。和 epb 搭配的預設 segment register 是 ss, 在處理 stack 時會用到。

一次只談簡單的例子, 這樣應該很容易理解。

2013年6月20日 星期四

x86 machine code 初探 (1) - base register address mode + displacement

這次新連載的東西可以寫好幾篇 (不輸給邓志那系列), 第貳篇我們來看看有 displacement 的 machine code。要學習的東西好多, 有資料結構 (之前沒學好, 要重新學習才行), compiler, lisp, forth, cortex m3 context switch, linker 的工作原理, 我知道該學習 Knuth 的一次只專注在一件事情上, 不過每個項目都那麼有趣, 實在想快點搞懂。linker 的工作原理和 machine code 有關係, 靜下心來先把這些東西完成。

像冨樫義博那樣拖稿讓人非常討厭, 我喜歡荒木飛呂彥的出稿速度, 搞不好他真的有天堂之門, 我也希望擁有天堂之門的能力, 酷阿!

廢話說太多, 來看這兩個例子, 透過例子來理解 machine code 是最好的方法了, 所以這系列我都會以例子來說明:
  1. base register address mode + displacement8
  2. base register address mode + displacement32

用 32bit 組譯出來的 machine code。

#practice x86 machine code
#.code16
.code32
.text
.global begin
begin:
  sub 126(%edi), %edi

intel syntax: sub edi, [edi+126]
註: 這個例子是 32bit mode

objdump -d address_mode.elf
1
2 address_mode.elf:     file format elf32-i386
3
4
5 Disassembly of section .text:
6
7 00000100 <_text>:
8  100:  2b 7f 7e                sub    0x7e(%edi),%edi

opcode: 2b
http://css.csail.mit.edu/6.858/2011/readings/i386/SUB.htm
2B  /r    SUB r32,r/m32    2/7    Subtract dword register from r/m dword

modrm: 7f -> 0111 1111 -> 01 111 111
mod: 01
reg: 111 (edi)
r/m: 111

mod: 01 (32bit)
[EAX]+disp83000
[ECX]+disp8 001
[EDX]+disp8 010
[EBX]+disp8 011
[--]+disp8 100
[EBP]+disp8 101
[ESI]+disp8 110
[EDI]+disp8 111

查表得到 (這個表在 intel 手冊查得, 有分 16/32 bit 兩種不同表格)
mod:01, r/m:111 => [EDI]+disp8 => [EDI] + 0x7e => [EDI + 126]
2b 7f 7e 就是這麼來的。



#practice x86 machine code
#.code16
.code32
.text
.global begin
begin:
  add 0x12345678(%edi), %esi
intel syntax: add esi, [edi+12345678h]

objdump -d address_mode.elf
1
2 address_mode.elf:     file format elf32-i386
3
4
5 Disassembly of section .text:
6
7 00000100 <_text>:
8  100:  03 b7 78 56 34 12       add    0x12345678(%edi),%esi

add opcode: http://css.csail.mit.edu/6.858/2011/readings/i386/ADD.htm
03 /r   ADD r32,r/m32      2/6    Add r/m dword to dword register

modrm: b7 -> 1011 0111 -> 10 110 111
mod:10
reg: 110 (esi)
r/m: 111

mod: 10 (32bit)
[EAX]+disp32 000
[ECX]+disp32 001
[EDX]+disp32 010
[EBX]+disp32 011
[--][--]+ disp32 100
[EBP]+disp32 101
[ESI]+disp32 110
[EDI]+disp32 111

查表得到
mod: 10
r/m: 111
=> [EDI]+disp32 => EDI + 78 56 34 12 => [EDI + 0x 12345678]


來看個 16 bit 範例:
section:disp(base,index,scale)
# practice x86 machine code
.code16
.text
.global begin
begin:
  add 0x12(%bx, %si, 1), %si

03 70 12      add    0x12(%bx,%si),%si

16bit mode 沒有 scale 這欄位, 所以 1 就被拿掉了, 而 scale 1 和沒有 scale 是一樣的。
modrm: 70 -> 0111 0000 -> 01 110 000
mod: 01
reg: 110 (SI)
r/m: 000


mod: 01 (16bit)
[BX+SI]+disp8 000
[BX+DI]+disp8 001
[BP+SI]+disp8 010
[BP+DI]+disp8 011
[SI]+disp8 100
[DI]+disp8 101
[BP]+disp8 110
[BX]+disp8 111

查表得到

mod: 01

r/m: 000
[BX+SI]+disp8 => [BX+SI] + 0x12



在 16 bit 模式下把 scale factor 改成 2 會怎樣?

# practice x86 machine code
.code16
.text
.global begin
begin:
  add 0x12(%bx, %si, 2), %si

address_mode.S: Assembler messages:
address_mode.S:8: Error: `0x12(%bx,%si,2)' is not a valid base/index expression
make: *** [address_mode.o] Error 1

組譯就不會過, 現在你知道為什麼了。


2013年6月12日 星期三

x86 machine code 初探 (0) - base register address mode

我從來沒想過會學習 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 就在談這個。

不過我搞錯了, 想要做這件事情, 不需要理解 x86 machine code, elf 檔案格式把這些資訊都處理好了, 只需要解析 elf 檔案即可。這樣也好, 要不然 arm/elf 再來一次, 我可受不了。

讓我們從 intel memory address 開始。intel 著名的 segmentation memory address, 將記憶體位址分為 segment part, offset part, 本文章重點擺在 offset part。而台灣翻譯的基底/索引定址法 (中國的翻譯則是 ...) 則為 base/index。

offset part 有三個欄位:
  1. base register
  2. index register multiplied 1, 2, 4, 8 (1, 2, 4, 8 被稱為 scale factor)
  3. 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):


這是 1987 年的書 (我寫這篇文章的時間是 20130612), 在電腦界這麼快速更新的時代, 照理說應該是過期的書籍, 不過由於相容性的緣故, 裡頭提到的東西到現在都還是可以用的, 而且簡單不少 (也沒有  64 bit mode), intel 手冊已經變得又厚又硬難以閱讀, 而這本書講的比較好理解。有些術語和最新的 intel 手冊有些不同, 不過不影響理解。

之前在閱讀 IBM 80X86 組合語言實務被其複雜的定址模式搞得我好亂, 現在一次把它搞懂。這些複雜的 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 數目:
  1. prefix 0-4
  2. opcode 1-2
  3. modrm 0-2
  4. displacement 0-4
  5. 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

有好幾個, 看以下這個:
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 玩 machine code 的朋友一定要試試。

某聚會上我的分享, 就是以這篇為主。


ref:
  1. x86/x64 指令编码内幕(适用于 AMD/Intel): http://www.mouseos.com/x64/index.html
  2. 学习 OpCode: http://www.luocong.com/learningopcode.htm
  3. Programming THE 80386
  4. http://ref.x86asm.net/coder32.html
  5. XED2 User Guide (intel 提供的方便工具 by ptt merckhung): https://software.intel.com/sites/landingpage/pintool/docs/56759/Xed/html/main.html