MIPS架構上函數調用過程的堆棧和棧幀


轉載於CSDN:http://blog.csdn.net/do2jiang/article/details/5404566

   在計算機科學中,Call stack是指存放某個程序的正在運行的函數的信息的棧。Call stack和stack frames組成,每個stack frame對應於一個未完成運行的函數。

  在當今流行的計算機體系架構中,大部分計算機的參數傳遞,局部變量的分配和釋放都是通過操縱程序棧來實現的。棧用來傳遞函數參數,存儲返回值信息,保存寄存器以供恢復調用前處理機狀態。每次調用一個函數,都要為該次調用的函數實例分配棧空間。為單個函數分配的那部分棧空間就叫做stack frame,也就是說,stack frame這個說法主要是為了描述函數調用關系的。

 

  Stack frame組織方式的重要性和作用體現在兩個方面:

  第一:它使調用者和被調用者達成某種約定。這個約定定義了函數調用時函數參數的傳遞方式,函數返回值的返回方式,寄存器如何在調用者和被調用者之間進行共享。

  第二:它定義了被調用者如何使用它自己的stack frame來完成局部變量的存儲和使用。

  1. 上圖描述的是一種典型的(MIPS 32)嵌入式芯片的stack frame組織方式。
  2. 這張圖中,計算機的棧空間采用的是向下增長的方式。
  3. sp(stack pointer)就是當前函數的棧指針,它指向的是棧底的位置。
  4. Current Frame所示即為當前函數(被調用者)的frame。
  5. Caller's Frame是當前函數的調用者的frame。
  6. 每個frame中所存放的內容和存放順序,則由目標體系架構的調用約定(calling convention)定義。
  7. MIPS O32調用約定規定了所占空間不大於4個比特的參數應該放在從$4到$8的寄存器中,剩下的參數應該依次放到調用者stack frame的參數域中,並且在參數域中需要前四個參數保留棧空間。
  8. 如果被調用者需要使用$16到$23這些保留寄存器(saved register),就必須先將這些保留寄存器的值保存在被調用者stack frame的保留寄存器域中,當被調用者返回時恢復這些寄存器值。
  9. 當被調用者不是葉子函數時,即被調用者中存在對其它函數的調用,需要將RA(return address)寄存器($31)值保存到被調用者stack frame的返回值域中。
  10. 被調用者所需要的局部變量,應保存在被調用者stack frame的本地變量域中。

 

  1. 在沒有BP(base pointer)寄存器的目標架構中,進入一個函數時需要將當前棧指針向下移動n比特,這個大小為n比特的存儲空間就是此函數的stack frame的存儲區域。此后棧指針便不再移動,智能在函數返回時再將棧指針上這個偏移量恢復棧現場。由於不能隨便移動棧指針,所以寄存器壓棧和出棧都必須指定偏移量。

 

  1. 在RISC計算機中主要參與計算的是寄存器,saved registers就是指在進入一個函數后,如果某個保存原函數信息的寄存器會在當前函數中被使用,就應該將此寄存器保存到堆棧上,當函數返回恢復此寄存器值。而且由於RISC計算機大部分采用定長指令或者定變長指令,一般指令長度不會超過32個位。而現代計算機的內存地址范圍已經擴展到32位,這樣在一條指令里就不足以包含有效的內存地址,所以RISC計算機一般借助於一個返回地址寄存器RA來實現函數的返回。幾乎在每個函數調用中都會使用到這個寄存器,所以在很多情況下RA寄存器會被保存在堆棧上以避免被后面的函數調用修改,當函數需要返回時,從堆棧上取回RA然后跳轉。移動SP和保存寄存器的動作一般處在函數的開頭,叫做function prologue;恢復這些寄存器狀態的動作一般放在函數的最后,叫做fuction epilogue。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM