(本文都在考慮 System V ABI AMD64 blahblah,沒有考慮微軟的情況)

最近在學習彙編語言,於是碰到了一個小問題:函數調用的時候,哪些寄存器可以不用壓棧直接用,用完以後也不用從棧裡面取回來呢?嗯比如我們知道,傳遞參數的時候,整數依次通過 %rdi, %rsi, %rdx, %rcx, %r8, %r9 來傳遞,傳參數用的寄存器我當然可以隨便改啦,那麼問題是如果我們這個函數只有 5 個參數,%r9 我能不能隨便改呢?

然後我發現文檔上說的很清楚。。。(x86-64.org 好像上不去了,不知道該貼哪個鏈接了。。。)

見圖 3.4:寄存器使用

調用過程中
寄存器 用處 要不要保護

%rax 臨時寄存器;參數可變時傳遞關於 SSE 寄存器 不要
用量的信息;第 1 個返回值寄存器

%rbx 被調者保存的寄存器;或用作基指針 要

%rcx 用來給函數傳遞第 4 個整數參數 不要

%rdx 用來給函數傳遞第 3 個整數參數 不要

%rsp 棧指針 要

%rbp 被調者保存的寄存器;或用作幀指針 要

%rsi 用來給函數傳遞第 2 個參數 不要

%rdi 用來給函數傳遞第 1 個參數 不要

%r8 用來給函數傳遞第 5 個參數 不要

%r9 用來給函數傳遞第 6 個參數 不要

%r10 臨時寄存器,用來傳遞函數的靜態鏈指針 不要

%r11 臨時寄存器 不要

%r12-r15 被調者保存的寄存器 要

%xmm0–%xmm1 用來傳遞和返回浮點參數 不要

%xmm2–%xmm7 用來傳遞浮點參數 不要

%xmm8–%xmm15 臨時寄存器 不要

%mmx0–%mmx7 臨時寄存器 不要

%st0 臨時寄存器;用來返回 long double 參數 不要

%st1–%st7 被調者保存的寄存器 不要

%fs 留給系統用(作線程特定數據寄存器) 不要

(順便吐槽一下知乎的表格功能根本沒有)嗯然後就看得特別清楚了,所有寫「不要」的寄存器都可以拿來隨便用。然後關於 SSE 寄存器的問題文檔里寫了一段話:

對於用 varargs 或 stdargs 的函數(沒原型的調用或者對定義中含省略號(...)函數的調用) %al [14] 當作隱藏參數使用,表明 SSE 寄存器的用量。%al 的內容不必和寄存器用量吻合,但是一定要是 SSE 寄存器用量的一個上界而且落在開區間 0-8 里。

腳註 14 說要注意 %rax 的其他部分是未定義的,只有 %al 的內容是定義了的。

那個「靜態鏈指針」是啥我現在還沒搞明白,百度查到了好多編譯器的文檔但是沒有任何解釋,Google 被牆了 QAQ,(我猜可能 MIPS 之類的架構上用的比較多),希望知道的同學告訴我呀~

推薦閱讀:

相关文章