有關調用約定的歷史 第二部分
預告
今天的文章主要是延續之前有關調用約定的主題,接下來我們要講述的內容,對於我們後面的一些討論議題會比較有幫助。有個需要注意的地方是:在眾多的硬件平台上,只有8086和x86平台存在多個調用約定,其他的平台都只有一個。我們接下來會深入到有關32位調用約定的細節,也許很多人都不太關心這個,但是還是值得講一講。
All
在這篇文章裏列出的所有的處理器都是RISC類型,這意味着:處理器上有搭載很多寄存器,這些寄存器都提供通用的功能,而不是某些定製化的功能。這裏有個例外:零值寄存器是直接硬件連線實現的。掛接到寄存器上的功能都受到調用約定的影響。
在處理器的早期階段,調用指令call會保存返回地址到一個寄存器,而不是保存在堆棧上。這其實也是一件好事,因為處理器根本不需要了解堆棧的細節信息,這個信息由調用約定來指明。
和之前一樣,寄存器或者棧空間被用來傳遞參數和返回值。
你可以注意到,所有針對RISC處理器的調用約定基本都是差不多的。但是對於8086和x86平台來説,它的調用約定確實是比較奇怪。
Alpha AXP
Alpha AXP(“AXP”是一個人造的首字母縮寫單詞,實際上它沒有什麼特別的意思),這款處理器搭載了一系列的32位寄存器,其中有一個硬連接的零值寄存器。根據慣例,這些寄存器中有一個是”棧幀”寄存器,還有一個是”返回地址”寄存器,還有另外兩個是和參數傳遞無關的特殊功能寄存器。
當傳遞參數的時候,前面6個參數使用寄存器來傳遞,而剩下的則是通過堆棧來傳遞。如果是一個可變參數,則所有的參數都會使用堆棧來傳遞,這樣它們就可以使用數組的方式來訪問。
剩下的幾個寄存器都是被保留的,其中一個用來返回值,剩下的13個Scratch寄存器。總的來説,32個寄存器被分類為:1個零值寄存器,1個棧幀寄存器,1個返回值寄存器,2個特殊功能寄存器,6個參數傳遞寄存器,7個保留寄存器,1個返回值寄存器和13個Scratch寄存器。
另外請注意:在Alpha AXP處理器上的函數名稱都是完全未修飾(undecorated)的。
MIPS R4000
前4個參數都通過寄存器a0, a1, a2和a3來傳遞,剩下的則通過堆棧傳遞。更進一步地,在堆棧上還有4個所謂的”死區”,這這個區域可以用來模擬這4個寄存器參數從堆棧來傳遞。它們主要被用在被調用函數中,用來將寄存器參數傳遞到堆棧上,這個對於可變參數十分方便。
在MIPS R4000處理器上的函數名稱都是完全未修飾(undecorated)的。
PowerPC
前8個參數通過r3-R10寄存器來傳遞,返回值則通過手動的方式進行管理。至於其他的參數如何,我就記不太清了。在PowerPC處理器上的函數名稱都是修飾(decorated)的。
總結
關於MIPS和PPC這兩種處理器,我不是很熟悉,所以上面有關它們的討論可能不是特別準確,但是我想基本原理的講述應該還是沒啥問題的。
最後
Raymond Chen的《The Old New Thing》是我非常喜歡的博客之一,裏面有很多關於Windows的小知識,對於廣大Windows平台開發者來説,確實十分有幫助。本文來自:《The history of calling conventions, part 2》
【來源:漫漫開發路】
聲明:轉載此文是出於傳遞更多信息之目的。若有來源標註錯誤或侵犯了您的合法權益,請作者持權屬證明與本網聯繫,我們將及時更正、刪除,謝謝。 郵箱地址:newmedia@xxcb.cn