
Re: [理工] 計組 第一章

看懂這段程式前我們要先有兩個概念
1. 原函式(caller)與被呼叫函式(callee)的關係
呼叫函式前因為callee會用到暫存器
所以要先將暫存器的變數存到stack中
以免原來在暫存器中的值被蓋掉
導致callee return之後caller無法繼續執行
一般儲存變數到stack的工作由caller跟callee分工
caller負責存a開頭跟t開頭的暫存器
而ra跟s開頭的暫存器交由callee負責存
原因是如果callee沒有用到這些暫存器就可以不用花時間去存
2. 這個程式可以想成是這樣運作的:
https://imgur.com/2brKrPw.jpg

所以是main呼叫f (此時main是caller、f是callee)
然後f呼叫func (此時f是caller、func是callee)
有了這兩個概念後我們就來看這段程式
https://imgur.com/xizcMRg.jpg

因為f是main的callee又要當caller呼叫func
所以要store ra跟s開頭的暫存器到stack中
以免等等被func改一改f回不去main
等callee return之後再load回來
這就是L1~L3跟L9~L11做的事情
而這邊為什麼要存s0我們等等再討論
存完stack之後就可以呼叫func了
注意此時f是caller、func是callee
呼叫前應該要設定引數a0=a, a1=b
但原本的a0, a1裡面就已經分別是a, b了
所以這裡就不再多設定一次
而L4那行move s0 a2是在做什麼的呢?
呼叫callee前caller應該要把等等callee return後
還要用的a開頭暫存器存起來(就是a2=c這個值)
因為我們不知道func的運作
(func可能還要再call其他函式會用到很多引數)
照理來說存到stack是最簡單的做法
(sp-4之後store到stack中等return後再load回來)
但這裡用了另一個做法就是把a2暫存到s0之中
所以等callee return之後要用a2就直接去s0找即可
所以L4就是在把a2存到s0中
這就是為什麼剛剛L1~L3在存stack的時候L3要多存一個s0
因為main跟f之間是caller跟callee的關係
而f (callee)這個函式要用到s0這個暫存器
所以在開始前要負責把main (caller)的s0內容先存起來
同理,當L5呼叫func函式之後
如果func中有要用到s0這個暫存器
也要在func開始前把s0存到stack中
(不過這就是func的事了跟我們現在在寫f無關)
了解L4之後應該就海闊天空了
L5跳到func去執行函式return之後
回傳值又要當作引數再呼叫一次func
L6, L7就是在做呼叫前的引數設定
L7這裡就用到剛剛被我們存到s0的a2=c
L8這裡一樣引數設定完跳到func去執行函式
等return之後load回f最一開始被我們存進stack的變數
再來就可以返回main,就是L12
--
※ 發信站: 批踢踢實業坊(ptt.cc), 來自: 114.136.148.186
※ 文章網址: https://www.ptt.cc/bbs/Grad-ProbAsk/M.1541781667.A.7DD.html
→
11/10 00:42,
7年前
, 1F
11/10 00:42, 1F
我只是把張凡說的打出來而已XD
他真的是個好老師覺得受益良多啊
→
11/10 00:53,
7年前
, 2F
11/10 00:53, 2F
→
11/10 00:55,
7年前
, 3F
11/10 00:55, 3F
→
11/10 00:56,
7年前
, 4F
11/10 00:56, 4F
→
11/10 00:56,
7年前
, 5F
11/10 00:56, 5F
→
11/10 00:56,
7年前
, 6F
11/10 00:56, 6F
→
11/10 00:56,
7年前
, 7F
11/10 00:56, 7F
→
11/10 00:57,
7年前
, 8F
11/10 00:57, 8F
→
11/10 01:01,
7年前
, 9F
11/10 01:01, 9F
→
11/10 01:11,
7年前
, 10F
11/10 01:11, 10F
→
11/10 01:11,
7年前
, 11F
11/10 01:11, 11F
推
11/10 07:17,
7年前
, 12F
11/10 07:17, 12F
→
11/10 07:17,
7年前
, 13F
11/10 07:17, 13F
→
11/10 07:22,
7年前
, 14F
11/10 07:22, 14F
→
11/10 07:22,
7年前
, 15F
11/10 07:22, 15F
→
11/10 07:25,
7年前
, 16F
11/10 07:25, 16F
→
11/10 07:25,
7年前
, 17F
11/10 07:25, 17F
main呼叫f之前(此時main是caller)
也要保護自己的變數(a&t開頭暫存器)
只是那是main的事,這裡是在寫f
也不一定會是main呼叫f
也有可能是另外一個函式G呼叫f
如果G同時也是caller跟callee
G除了a&t開頭也要保護ra&s開頭暫存器
※ 編輯: skyHuan (114.136.235.245), 11/10/2018 10:07:04
推
11/10 16:06,
7年前
, 18F
11/10 16:06, 18F
推
11/10 22:03,
7年前
, 19F
11/10 22:03, 19F
討論串 (同標題文章)