這是一個建立於 的文章,其中的資訊可能已經有所發展或是發生改變。
前言
本文是我學習Go彙編的一些心得,網上關於Go的彙編資料實在是太少了,本人電腦不是科班,所以可能會有錯誤。
進程記憶體位址空間
作業系統執行程式時,會把程式的二進位部分載入進記憶體,同時分配一定的記憶體空間。如所示
TEXT/Code segment
TEXT segment,或者叫Code segment,儲存了程式的指令。
Data segment
Data segment 保留著進程初始化的全域和靜態變數。這個資料區段可以變為初始化唯讀地區(initialized read-only area)和初始化讀寫地區(initialized read-write area)。
Gvar Section
一個全域變數初始化和儲存在data segment。這個地區可讀/寫,但是不能在進程之間共用資料。
BSS Section
這個section儲存著未初始化的資料。 這個section的又叫做零初始化資料section(zero-initialized data section)
Heap Section
heap是進程的線性增長地址空間,當程式使用malloc()擷取的動態記憶體,這份記憶體就是在heap之中。heap地區是在BSS segement之後,並會“增長”到更高的地址空間。heap地區是所有共用庫、動態模組都可見的。
Stack Segment
這個Segement儲存所有局部變數。當調用函數時,這個函數的局部變數就全部分布在stask上(這個函數就形成了stack frame)。當函數退出時,所有該函數相關的局部變數會自動從stask上退出。其他資訊,包括返回地址和局部參數,也是儲存在stack的stack frame之上。stack是LIFO(last in first out 先進後出)結構,一般是分配在記憶體的高地址上,因此是向低位增長,還有每個寄存器,中間值或者stack frame。
跟Go asm有什麼關係?
Go有幾個虛擬寄存器
- FP (stack frame pointer) stack幀低位指標,指向參數和局部變數,offset為正數
- SP(virtual stack pointer)stack幀高位指標(棧頂),offset應為負數
- PC (program counter) 程式計數器,負責跳轉和分支
- SB (static base pointer) 靜態全域符號(symbol)
其中FP和SP的區別如所示:
High +-----------------+ | | | Stack frame 0 | | | +-----------------+ | | <---+ SP | Stack frame 1 | | | <---+ FP Low +-----------------+
這裡有個疑問的地方,啥是符號(symbol),根據Symbol裡的解釋是:
符號(symbol)是協助人們標記特定記憶體位址的東西
也就是說例如
TEXT DEMO(SB)
就代表指向code segment中代表DEMO函數的記憶體位址。
寄存器
每種CPU都有不同的寄存器,AMD64平台裡常用的有以下幾個:
- [A-D]X //通用的64位寄存器
- R8-15 // 之前的其實是A-Dx、SI、DI等寄存器佔用了
- SI // 源(source register)
- DI // 目的地 (destination register)
- X0-15 // sse用
- Y0-15 // avx2 用
瞭解完記憶體結構和寄存器後,下一篇將學習各種符號的意義:)