# x86 Assembly
## Register

### General puspose
- rax (accumulator)
- rbx (base)
- rcx (count)
- rdx (data)
- rsi (source index)
- rdi (destination index)
- rbp (base pointer)
- rsp (stack pointer)
- rip (instruction pointer)
> rip could not be dest.
用於記錄下一個要執行的instruction
### r[a-d]x register layout
```
+----------+
| | | |
+----------+
0 63
```
- r[a-d]x (64 bits)
- e[a-d]x (32 bits)
- [a-d]x (16 bits)
- [a-d]h (8 bits)
- [a-d]l (8 bits)
### Stack

由兩個 register (rsp 與 rbp) 指向的記憶體空間,用來記錄:
- return address
- local variable
一開始 rbp 與 rsp 的位址相同
```assembly=
push rbp
mov rbp, rsp
```
這時如果 push 一組資料進來, rsp 會往 low address 前進 (rsp 存放的位址會越來越小)。
### push and pop
- push: 將資料放進 stack
```assembly=
push rax
```
將 rax 的 value 放進 stack 。
- pop: 將最上層資料捨棄
```assembly=
pop rcx
```
將上層資料存到 rcx 並捨棄上層資料。
```assembly=
pop word [rbx]
```
將上層資料存到 rbx 存放的地址(也就是 *rbx) 並捨棄上層資料。
### function call
假設 `main()` 函式呼叫了 `funcA()` , Stack 與相關暫存器的變化如下:
1. 將 return address (回到 `main()`) 推入 stack:

2. 接著我們會將 `main()` 的 rbp 推入 stack :
```assembly=
push rbp
```

3. 將 rbp 移動到 rsp 的位址:
```assembly=
mov rbp, rsp
```

4. 分配空間給 `funcA()` (也就是將 rsp 向下移動):
```assembly=
sub rsp, 0x10
```

5. 等到 `funcA()` return 時,會呼叫 leave :
```assembly=
mov rsp, rbp
pop rbp
```


6. 這時 rsp 已經指向 main 的 return address 了,接著呼叫 ret 時,rip 就會指向 return address,並且將 stack frame 的狀態回復到 main 的 stack frame 。
### instruction syntax
- syntax
```assembly=
mov dest, source
```
- example
- `mov rax, rbx` 等於 `rax = rbx`
- `mov rax, [rbx-4]` 等於 `rax = *(rbp-4)`
- `mov [rax], rbx` 等於 `*rax = rbx`
- `lea eax,[ebx+8]` 等於 `eax = (ebx+8)`
### [運算指令](https://zh.m.wikibooks.org/zh-tw/X86_%E6%B1%87%E7%BC%96/%E7%AE%97%E6%9C%AF)
- add
- sub
- imul 有號乘法
- idiv 有號除法
- and
- or
- xor
- neg (x = -x)
- not
- inc (x = x + 1)
- dec
### 型態
- byte: 1 byts
- word: 2 bytes
- dword: 4 bytes
- qword: 8 bytes
舉例:
```assembly=
mov byte [rcx], 0x61
mul word [rax], 0x87
inc dword [rbp]
not qword [rsp]
```
> **注意!**:
> dest 與 source 的型態需要相同
### Compare 與 Flag
```assembly=
cmp val1, val2
```
會比較 val1 與 val2 是否相等,並將結果存到 flag register 當中。
> 一般來說會搭配 [jump 指令](https://www.felixcloutier.com/x86/jcc)。
### [system call](https://blog.rchapman.org/posts/Linux_System_Call_Table_for_x86_64/)
### conditional statement
1. if/else
```c=
if(rax < 5){
// ...
}
else if (rax >= 5 && rax < 10){
// ...
}
else{
// ...
}
```
轉換成 x86 組合語言:
```assembly=
cmp rax, 5
jae Lelseif
; do something
jmp Lend
Lelseif:
cmp rax, 10
jae Lelse
; do something
jmp Lend
Lelse:
; do something
Lend:
```
2. loop
```c=
for (int i = 0; i < 10; i++){
}
```
轉換成 x86 組合語言:
```assembly=
mov rcx, 0
loop:
cmp rcx, 10
jae lend
; do something...
inc rcx
jump loop
lend:
```
### funtion parameter (x86_64)
function 的參數會依序傳給:
- rdi, rsi, rdx, rcx, r8, r9
- 如果超過 6 個參數,通通丟到 Stack 內
## Reference
- [BambooFox 社課](https://www.youtube.com/watch?v=h_OoO_YhtAE)
- [你所不知道的 C 語言: 函式呼叫篇](https://hackmd.io/@dange/rk9xmgHKX?type=view)