---
# System prepended metadata

title: 零散沒用的小知識
tags: [Computer Science Basic, program basic]

---

# 零散沒用的小知識

## x86組語中的 lea mov
關於實現 ` $edx = $eax+$ebx+8`
```
1   add eax, ebx
2   add eax, 8
3   mov edx, eax    
```
```
1   lea edx, [eax+ebx+8]
```
`lea`擅長處理複雜的地址處理，並且該操作不會改變旗幟(flag)的更動，相較於使用`mov`，`mov`會先進行`add`、`sub`等等的操作都會改變旗幟(flag)


 ## __x86.get_pc_thunk.ax
 先講結論，該Binary是PIC(Position Independent Code)的時候會使用，因為函數與位置無關，所以我們使用`__x86.get_pc_thunk.ax`找到需要使用的函數、變數位置，加上偏移量就可以調用
![image](https://hackmd.io/_uploads/B1-mOxPP0.png)
先記住`__x86.get_pc_thunk.ax` 下一條指令(`add eax, 0x2e27`)這個待會會用到，很重要

![image](https://hackmd.io/_uploads/B1OqVgwPR.png)
可以看到`__x86.get_pc_thunk.ax`只做一件事
```
---> 0x5655621d <__x86.get_pc_thunk.ax> mov eax, DWORD PTR [esp]
     0x56556210 <__x86.get_pc_thunk.ax> ret
```
他把`$esp`所指向的*content*放入`$eax`
![image](https://hackmd.io/_uploads/B1xQ8evP0.png)
因為call一個function會將下一條指令壓入**stack**中，所以此時`$esp`所存的內容就是前面第一張圖所說的下一條指令(`add eax, 0x2e27`) 
:::info
這邊要注意，一般而言caller(呼叫function的function，這邊為`main`)只會存next PC(也就是return address)，而做stack操作(save `$ebp`、create stack space)都是callee(這邊為`_x86.get_pc_thunk.ax`)在做的，但可以看到他並沒有做stack的操作，所以`$esp`是next PC，而`$ebp`則沒有變動。
:::
![image](https://hackmd.io/_uploads/B1SeolvDA.png)
可以看到此時`$eax` 就如前面所說已經存好next PC了
![image](https://hackmd.io/_uploads/S1qmilvPC.png)
return回main function後可以看到準備要執行`add eax,0x2e27`，意思是基於`add eax,0x2e27`這條指令的地址在加上一個`0x2e27`的偏移

> 為什麼要這樣?
> 
因為該binary是PIC，位置不是compiler time時就決定好的，但他的相對位置是固定的，譬如說我知道某個函數是在`*main + 0x100`，那我就能透過main找到該函數，不管該binary是load到memory的哪裡，因為他們的相對位置都是固定的
![image](https://hackmd.io/_uploads/r186nlPwA.png)
可以看到`$eax`現在指到GOT表，因為我們不知道GOT表的實際位置，所以我們使用這種方法去查找GOT表的位置，而這邊是因為我下面call了puts，所以他需要事先知道GOT表的位置

`_x86.get_pc_thunk.ax` 主要就是因為實現PIC而存在的，因為程式碼與位置無關所以我們使用一個function去查找該程式碼所需要的東西



