什麼是堆疊

最後放入的元素最先取出的後進先出(LIFO)資料結構。放入元素的操作稱為 push,取出的操作稱為 pop。用於管理函式呼叫的返回位址與區域變數(呼叫堆疊)、計算逆波蘭表示法的算式、深度優先搜尋等。

日文名稱: スタック

「堆疊」出現在8領域的34道練習題中(指令集與組合語言, 連結器與載入器與執行檔格式, 資料結構與演算法等)。

這個名詞所屬的領域: 資料結構與演算法

練習堆疊的題目

不呼叫其他函式的函式(葉函式、leaf function),在很多情況下不需要將ra保存到堆疊。下列何者是其理由?

  1. A因為葉函式不使用ret指令
  2. B因為葉函式的返回位址是由CPU自動堆入堆疊
  3. C因為不呼叫其他函式,ra不會被覆寫,返回位址會原封不動地保留
查看答案與解析

正確答案:C. 因為不呼叫其他函式,ra不會被覆寫,返回位址會原封不動地保留

ra會在每次呼叫函式的jal時被覆寫,所以呼叫其他函式的函式,必須一開始就將自己的返回位址保存到堆疊。葉函式不使用jal,所以ra不會被破壞,不必保存就能ret。此外,如果也不使用被呼叫端保存的暫存器,甚至不需要建立堆疊框(stack frame)。x86的call指令一定會將返回位址堆入堆疊,這是與RISC-V的差異。

在RISC-V中撰寫呼叫自己的遞迴函式時,若忘了將ra保存到堆疊,會發生什麼事?

  1. Ara在內層的呼叫中被覆寫,外層的函式無法返回正確的呼叫端
  2. BCPU會自動保存ra,所以不會有任何問題
  3. C無論遞迴的深度,計算結果都會變成2倍
查看答案與解析

正確答案:A. ra在內層的呼叫中被覆寫,外層的函式無法返回正確的呼叫端

遞迴呼叫的jal會將ra覆寫為「自己內部呼叫的下一個指令」。若沒有保存,外層的函式在ret時就不會回到原本的呼叫端,而是回到自己內部,導致重複相同的地方或發生錯誤動作。因此,呼叫其他函式的函式,規定要在序言將ra保存到堆疊,並在結尾還原。

解析中的「堆疊」

出現「堆疊」的題目(34題)

  1. 不呼叫其他函式的函式(葉函式、leaf function),在很多情況下不需要將ra保存到堆疊。下列何者是其理由?
  2. 在RISC-V中撰寫呼叫自己的遞迴函式時,若忘了將ra保存到堆疊,會發生什麼事?
  3. 將行程的堆積與堆疊配置成中間隔著寬廣的空閒區域、朝相反方向延伸,其優點為下列何者?
  4. 當遞迴過深而超過堆疊的上限時,在Linux等系統上一般會發生的事,下列何者正確?
  5. 在沒有MMU的小型微控制器上,關於堆疊使用過量,應注意的事項下列何者正確?
  6. 對空的堆疊依序進行 push 1、push 2、pop、push 3、push 4、pop、pop 的操作。依序排列以 pop 取出的值,下列何者正確?
  7. 以逆波蘭表示法(後序式)寫成的算式「3 4 + 2 * 5 −」,用「遇到數字就推入堆疊,遇到運算子就取出2個值計算並推入結果」的方法求值。結果為多少?其中運算子左側的值是先推入的那一個。
  8. 以元素數為5的整數型陣列 st 與整數型變數 top 表示堆疊。st 的元素一開始全為0,top 從0開始。push(v) 先把 top 加1再執行 st[top] ← v,pop() 回傳 st[top] 的值後把 top 減1(不改變 st 的元素)。執行下列程式後 top 與 st 為下列何者?
  9. CPU 的程式計數器(PC)所保存的是下列何者?
  10. 在程式中呼叫副程式(函式)時,一般用來暫時保存返回位址等的區域是下列何者?
  11. 下列何者是RISC-V指令「lw t0, 8(sp)」的動作?
  12. 下列何者是制定呼叫慣例(calling convention)的主要目的?
  13. 在RISC-V的標準呼叫慣例中,下列何者是用於傳遞整數引數與回傳值的暫存器?
  14. 在RISC-V的標準呼叫慣例中,呼叫一個有10個整數引數的函式時,第9個與第10個引數是在哪裡傳遞?
  15. 在RISC-V的呼叫慣例中,s0~s11被視為「被呼叫端保存(callee-saved)」的暫存器,下列何者是其意義?

出現這個名詞的比較

半導體、電子電路與資訊計算工具

相關名詞

變數 遞迴 返回位址 引數 呼叫慣例 回傳值 陣列 堆疊框 佇列 堆疊指標

前往名詞解釋列表