Lions' 本読み (120)
いやしかし昨日の勉強会ではずたぼろでした。読んではいますがそれが知識として脳に蓄積されない、というのは色々な意味で悲しい。とりあえずスタックフレームあたりの云々を再度確認しておく必要があるってことで csv 手続きとか cret 手続きのあたりを見てみます。
その前にまごろくさんスライドの 26 枚目から 28 枚目あたりを確認する必要あり。とその前に 21 枚目のスライドが先か。
まず main 関数の一部が以下。
sub S6,sp mov $1,-10(r5) mov $2,-12(r5) mov -12(r5),(sp) mov -10(r5),-(sp) jsr pc,*$_func
このあたりが 26 枚目のスライドの部分ですね。フレームポインタからの位置なパラメータが微妙に違いますがスルー。2、1 という順で func に渡す引数をスタックに push しています (呼び出す手続きに渡す引数はスタックを使ってやりとりされる)。
で、最後の jsr ですが、24 枚目のスライドに詳細な説明があります。上の例だと
- pc をスタックに push
- pc と pc に転送 (この例だと意味は無いですね)
- func 手続きに jmp
という形になります。スタックの様子てきに言うと 26 枚目の #20 の状態で言うと
- func 手続きからの戻り番地
- 一つめの引数
- 二つめの引数
という形になっている模様。次に 21 枚目のスライドにある func 手続きの命令を以下に引用します。
jsr r5,csv mov 4(r5),_c mov 6(r5),_d mov _c,r0 add _d,r0 jbr L2 jmp cret
スミマセン、jbr はスルーさせて下さい。27 枚目のスライドは csv 手続きにフォーカスされてますね。確認してみます。
とは言え、csv 手続きの前に jsr 命令ですね。
jsr r5,csv
- r5 の値 (前のフレームポインタ) をスタックに push
- pc (戻り番地) を r5 に
- csv に jmp
これ、24 枚目のスライドの下に記述されているソレなのか。これ、スタックは 27 枚目のスライドの #21 の状態になって r5 には戻り番地が格納されてる形。
そして csv の定義が以下 (スライドは 27 枚目)。
1419 .globl csv 1420 csv: 1421 mov r5,r0 1422 mov sp,r5 1423 mov r4,-(sp) 1424 mov r3,-(sp) 1425 mov r2,-(sp) 1426 jsr pc,(r0)
- r5 の値 (戻り番地) を r0 に退避 (1421)
- スタックポインタ (r6) の値を r5 に転送 (1422)
- r4 の値をスタックに push (1423)
- r3 の値をスタックに push (1424)
- r2 の値をスタックに push (1425)
ええと、csv が r5 に退避された戻り番地を r0 に転送してますね。で、1422 で r5 と r6 が同じ位置を指す形にして r2 から r4 を退避しています。
で、1426 でどうなるか、というと
- pc をスタックに push
- pc と pc に転送 (この例だと意味は無いですね)
- r0 が指してる命令に jmp
なんとなくムダにスタックを消費している気もしますが、このあたりを cret が解決してくださるのかどうか。
その前に cret が呼び出される前のスタックの状態はどうなっているかというと
- 1426 で push された PC の値
- r2 の値
- r3 の値
- r4 の値
- 直前のフレームポインタの値
- func 手続きからの戻り番地
- 一つめの引数
- 二つめの引数
という形で r5 は直前のフレームポインタの値が格納されているスタックの番地を指しているはず (1422 で設定)。
これを前提に cret の定義を確認してみます。定義は以下。
1429 .globl cret 1430 cret: 1431 mov r5,r1 1432 mov -(r1),r4 1433 mov -(r1),r3 1434 mov -(r1),r2 1435 mov r5,sp 1436 mov (sp)+,r5 1437 rts pc
28 枚目のスライドがこのあたりになりますね。で、フレームポインタの直上に r2 から r4 が退避されてます。ので、そこから値を復帰して 1435 にてフレームポインタの値をスタックポインタに代入しています。
で、1436 で直前フレームのフレームポインタを r5 に設定しています。で、1437 の rts ですが 25 枚目のスライドにフォローがあります。rts src は以下と等価とのこと。
- MOVE src,PC
- MOV (R6)+,src
フレームポインタの前には戻り番地が格納されていますのでそれが pc に格納されて呼び出し元に戻る、ということになりますね。
まとめとして
29 枚目のスライド、非常にありがたいです。
- フレームポインタが指すアドレスには呼び出し元のフレームポインタが格納
- スタックのその前には戻り番地が格納
- さらにその前には引数が格納
- スタックの後ろ (?) 側には r2 から r4 が退避される
レジスタが退避されなくなるのはいつ頃だったのだろう。