golang的偽寄存器
Go匯編為了簡(jiǎn)化匯編代碼的編寫,引入了PC、FP、SP、SB四個(gè)偽寄存器。四個(gè)偽寄存器加其它的通用寄存器就是Go匯編語(yǔ)言對(duì)CPU的重新抽象,該抽象的結(jié)構(gòu)也適用于其它非X86類型的體系結(jié)構(gòu)。
四個(gè)偽寄存器和X86/AMD64的內(nèi)存和寄存器的相互關(guān)系如下圖:

在AMD64環(huán)境,偽PC寄存器其實(shí)是IP指令計(jì)數(shù)器寄存器的別名。偽FP寄存器對(duì)應(yīng)的是函數(shù)的幀指針,一般用來(lái)訪問(wèn)函數(shù)的參數(shù)和返回值。偽SP棧指針對(duì)應(yīng)的是當(dāng)前函數(shù)棧幀的底部(不包括參數(shù)和返回值部分),一般用于定位局部變量。偽SP是一個(gè)比較特殊的寄存器,因?yàn)檫€存在一個(gè)同名的SP真寄存器。真SP寄存器對(duì)應(yīng)的是棧的頂部,一般用于定位調(diào)用其它函數(shù)的參數(shù)和返回值。
當(dāng)需要區(qū)分偽寄存器和真寄存器的時(shí)候只需要記住一點(diǎn):偽寄存器一般需要一個(gè)標(biāo)識(shí)符和偏移量為前綴,如果沒(méi)有標(biāo)識(shí)符前綴則是真寄存器。比如(SP)、+8(SP)沒(méi)有標(biāo)識(shí)符前綴為真SP寄存器,而a(SP)、b+8(SP)有標(biāo)識(shí)符為前綴表示偽寄存器。
總結(jié):
偽FP和硬件SP使用最多
偽FP(Frame pointer): arguments and locals --->用于訪問(wèn)函數(shù)傳入的參數(shù)
硬件SP(Stack pointer): top of stack --->棧頂?shù)刂?/p>
偽PC(Program counter): jumps and branches --->執(zhí)行指令的地址
偽SP(Stack pointer): top of stack --->棧底地址
偽SB(Static base pointer): global symbols --->全局靜態(tài)基指針,一般用來(lái)聲明函數(shù)或全局變量
硬件BP(Base pointer): base pointer-->位置同偽SP
golang的stack布局
if framepoiner_enabled==true,那么framesize是包含 clller's BP 的


過(guò)程:
下面的SP指硬件SP
- CALL調(diào)用方法C,將PC地址壓入return addr/parent return address
- 通過(guò)SUBQ操作SP擴(kuò)張C的棧(需要額外開辟8bit保存當(dāng)前的BP,即B的BP)
- 保存當(dāng)前BP寄存器中的值到棧底
- 運(yùn)行代碼邏輯
- 恢復(fù)棧底的BP值到BP寄存器
- 通過(guò)ADDQ操作SP收縮棧至return addr/parent return address
- 執(zhí)行RET,恢復(fù)return addr/parent return address的值到PC寄存器,繼續(xù)其他邏輯
golang函數(shù)調(diào)用時(shí)棧例子
func main() {
printsum(1, 2)
}
func printsum(a, b int) {
var ret = sum(a, b)
println(ret)
}
func sum(a, b int) int {
return a+b
}

這里不包含BP是因?yàn)樽隽撕?jiǎn)化,更好的展示棧調(diào)用的過(guò)程
參考:
https://blog.csdn.net/hel12he/article/details/103271937
https://hezhiqiang8909.gitbook.io/go/ch3-asm/ch3-04-func#3.4.5-tiao-yong-qi-ta-han-shu
https://hezhiqiang8909.gitbook.io/go/ch3-asm/ch3-02-arch#3.2.4-go-hui-bian-zhong-de-wei-ji-cun-qi