手続き呼び出しのまとめ

少し間があきましたが、こんばんは。

え、実はこの3日間くらいずっといボーッとしてたから更新なかったんだろって?
いやいや、まさかそんなことあるわけが・・・


まじめな話をしますと、ここ最近はずっとMIPSでの簡単なコードを書きながら、実際に高級言語(おもにC言語)で様々な分を書いた時の、実際の実行の様子がどうなっているかを勉強していました。
そんな訳で、ブログ書くにしても何載せようかちょっと迷っちゃってたんですよね・・・

今日載せるのは、手続き(関数)呼び出し時の一連の動作についてです。
MIPSにおいて、手続き呼び出し時の動作は以下の通り。



呼び出し側での処理(call時)

  • 呼び出し側における一時レジスタ($a0-$a3, $t0-$t9)をスタックに退避
  • 呼び出し先での引数を$a0-$a3にセット
  • (引数が5つ以上ある場合は、スタックへ積む)
  • jal命令でサブルーチンへ分岐


サブルーチン側での処理

  • $fp, $raレジスタをスタックへ退避
  • このときの$spを$fpに設定
  • (あれば)$spを下げて、手続き内でのローカル変数・$s0-$s7レジスタの退避領域を確保

(サブルーチンの主な手続き部分)

  • (あれば)$s0-$s7レジスタを復帰
  • $ra, $fpをスタックからレジスタへ復帰
  • jr $ra で戻り先へ分岐


呼び出し側での処理(return時)

  • call時と逆の手順でスタックから$a0-$a3, $t0-$t9を復帰

こんな感じですね。
コードでまとめると、例えば以下のような感じになります。

main:
	#part of execution...
	
	#part of call sub routine
	addi	$sp,	$sp,	-16	#shelter of $a0-$a3
	sw	$a0,	12($sp)
	sw	$a1,	8($sp)
	sw	$a2,	4($sp)
	sw	$a3,	0($sp)
	addi	$sp,	$sp,	-40	#shelter of $t0-$t9
	sw	$t0,	36($sp)
	sw	$t1,	32($sp)
	sw	$t2,	28($sp)
	sw	$t3,	24($sp)
	sw	$t4,	20($sp)
	sw	$t5,	16($sp)
	sw	$t6,	12($sp)
	sw	$t7,	8($sp)
	sw	$t8,	4($sp)
	sw	$t9,	0($sp)
	
	move	$a0,	$t0		#set of arguments
	move	$a1,	$t1
	move	$a2,	$t2
	move	$a3,	$t3
	addi	$sp,	$sp,	-16	#shelter of arguments
	sw	$t4,	12($sp)
	sw	$t5,	8($sp)
	sw	$t6,	4($sp)
	sw	$t7,	0($sp)
	
	jal	subr
	
	addi	$sp,	$sp,	16	#restore of $sp
	
	lw	$t9,	0($sp)		#restore of $t0-$t9
	lw	$t8,	4($sp)
	lw	$t7,	8($sp)
	lw	$t6,	12($sp)
	lw	$t5,	16($sp)
	lw	$t4,	20($sp)
	lw	$t3,	24($sp)
	lw	$t2,	28($sp)
	lw	$t1,	32($sp)
	lw	$t0,	36($sp)
	addi	$sp,	$sp,	40
	lw	$a3,	12($sp)		#restore of $a0-$a3
	lw	$a2,	8($sp)
	lw	$a1,	4($sp)
	lw	$a0,	0($sp)
	addi	$sp,	$sp,	16
	
	#continue main execution...
	
	jr $ra				#end of main
	
subr:
	addi	$sp,	$sp,	-8	#shelter of $fp and $ra
	sw	$fp,	4($sp)
	sw	$ra,	0($sp)
	move	$fp,	$sp		#$fp = $sp
	
	addi	$sp,	$sp,	-20	#secure area of local variale and $s0-$s7
#	sw	$s0,	0($sp)		#(shelter of save registers)
	#part of execution of subr...
	
#	lw	$s0,	0($sp)		#(restore of save registers)
	
	move	$sp,	$fp		#restore of $ra and $fp
	lw	$ra,	0($sp)
	sw	$fp,	4($sp)
	addi	$sp,	$sp,	8
	
	jr	$ra			#return of subr

では今日はこの辺で!