Introduction to x86 Assembly Instruction
2 minute read
這篇介紹一些基本的 intel x86 的組合語言指令,做個小筆記。
Arithmetic
- mov: 搬移 ``` mov (destination, source)
mov eax, 0 # 把 eax 歸零 mov eax, ecx # 把 ecx 寫入 eax 中,ecx 不變
<!--more-->
- add/sun: 加/減法運算
add/sub (destination, source)
add eax, 3 # eax = eax + 3 sub eax, ecx # eax = eax - ecx
\*eax 會被寫入新的值!
- inc/dec: 遞增/遞減
- neg: 取負數
inc/dec/neg (destination)
inc eax # eax++ dec ecx # ecx– neg eax # eax = -eax
- mul/imul: 無號(unsigned)乘法/有號(signed)乘法
mul/imul (source) 它會自動把結果寫入 eax,所以沒有 destination
mul ebx # eax = eax * ebx
imul 還有其他接受 destination, source 的格式,這裡就不一一列舉
- div/idiv: 無號(unsigned)除法/有號(signed)除法
div/idiv (source) 它會把商寫入 EAX, 餘數寫入 EDX 注意他的被除數是 EDX:EAX div ebx # eax = eax / ebx
如果是 dword 的運算,被除數是 EDX:EAX,商會在 EAX, 餘數在 EDX
如果是 word 的運算,被除數是 DX:AX,商會在 AX, 餘數在 DX
如果是 byte 的運算,被除數是 AX,商會在 AL, 餘數在 AH
## Compare and Conditional Jumps
這其實就是 if-else 敘述的 assembly code,主要的概念是,先透過 cmp 進行比較,設定 EFLAGS 上的一些位元,再透過 jump 系列指令依據不同的條件跳到不同的位址(更改EIP)
- cmp: 比較並設定旗標
cmp (op1, op2)
它會嘗試 op1 - op2,但結果不會寫入任何地方,也不會影響 op1 或 op2,唯一改變的是 EFLAGS 的旗標 (如 CF, ZF...等等),通常 cmp 會搭配 conditional jump 指令使用
- jmp: 直接跳轉到某個位址,類似 goto
jmp label
- Conditional jump 系列:
其他 jump 系列的如 jle (less or equal), jng (not greater) 等等,都是藉由 EFLAGS 的旗標決定是否跳轉
## Example
```c
for (int i = 0; i < 10; i++)
printf("%d", i);
編譯之後的 assembly:
0x804841c <main+17> mov DWORD PTR [ebp-0xc],0x0
0x8048423 <main+24> jmp 0x804843c <main+49>
0x8048425 <main+26> sub esp,0x8
0x8048428 <main+29> push DWORD PTR [ebp-0xc]
0x804842b <main+32> push 0x80484d0
0x8048430 <main+37> call 0x80482e0 <printf@plt>
0x8048435 <main+42> add esp,0x10
0x8048438 <main+45> add DWORD PTR [ebp-0xc],0x1
0x804843c <main+49> cmp DWORD PTR [ebp-0xc],0x9
0x8048440 <main+53> jle 0x8048425 <main+26>
# int i = 0
0x804841c <main+17> mov DWORD PTR [ebp-0xc],0x0
# 先跳到 main + 49 去 compare ,因為 for loop 會先比一次
0x8048423 <main+24> jmp 0x804843c <main+49>
# function call 的準備工作
0x8048425 <main+26> sub esp,0x8
0x8048428 <main+29> push DWORD PTR [ebp-0xc]
0x804842b <main+32> push 0x80484d0
# call printf 以及放掉 stack memory
0x8048430 <main+37> call 0x80482e0 <printf@plt>
0x8048435 <main+42> add esp,0x10
# i++
0x8048438 <main+45> add DWORD PTR [ebp-0xc],0x1
# 如果 i <= 9 的話就跳到 main + 26 繼續迴圈,否則往下跑結束迴圈
0x804843c <main+49> cmp DWORD PTR [ebp-0xc],0x9
0x8048440 <main+53> jle 0x8048425 <main+26>