mips
# Data segment .data # Text segment .text .globl main main: li $s0,1 # s0 = 1 li $s1,2 # s1 = 2 li $s2,3 # s2 = 3 add $t0,$s0,$s1 # t0 = s0 + s1 add $s3,$t0,$s2 # s3 = t0 + s2 jr $ra # end of program
#メモリからレジスタへデータ転送するデータ転送命令を一般にロード命令という。 --> lw #逆の命令をストア命令という。 -->sw #la:load address la $t0,src #定数のロード #li $R, C #定数値 C をレジスタ $R にロードする。load immediate #addi $s3, $3, 4 # $s3 = $3 + 4 li $t0, $t3 #これはだめ。 sw $s3, 12($t0)
cでいう、 int main() { #i, j, f, g, hはすでに値が格納されている。 if(i == j) { f = g + h; } else { f = g - h; } } //をアセンブラに書き換えてみる。
li $s0, 1 li $s1, 2 li $s2, 3 li $s3, 10 li $s4, 11 bne $s3, $s4, Else #真なら、elseに飛ぶという形。Cと逆になっていることに注意。 add $s0, $s1, $s2 j Exit Else: sub $s0, $s1, $s2 Exit:
while文。 LOOP: # ループの開始 slt $t4, $t2, $t3 # $t4 = ($t2<$t3) ? 1 : 0; beq $t4,$zero,ENDLOOP #while(i < n) 二つの命令でi < nが表現できる。 lw $t5,0($t0) # array[i] の値を $t5 にロード add $t1,$t1,$t5 # S = S + array[i] addi $t0,$t0,4 # $t0 = $t0 + 4 addi $t2,$t2,1 # i = i + 1 j LOOP # ENDLOOP: # ループの終了
戻り値を持たないものを「手続き」、戻り値をもつものを 「関数」と呼ぶ。
# Data Segment .data .globl msg msg: .asciiz "Hello World.\n" # Text Segment .text .globl main main: addi $sp,$sp,-4 # スタックポインタを 1 ワード分ずらす add $t0, $ra, $zero #$ra = 00400018 sw $ra,0($sp) # $ra をスタックに退避 jal hello # 関数 hello を呼び出す lw $ra, 0($sp) # スタックに退避した $ra を元に戻す addi $sp,$sp,4 # スタックポインタを元に戻す add $t0, $ra, $zero #$ra = 00400018 jr $ra # end of program .globl hello hello: li $v0,4 la $a0,msg syscall add $t1, $ra, $zero #$ra = 00400034 jr $ra
# Data Segment .data .globl mydata # 変数 mydata を定義する mydata: .word 10 # mydata = 10 .globl S S: .space 4 # Text Segment .text .globl main main: addi $sp,$sp,-4 # スタックポインタを 1 ワード分ずらす sw $ra,0($sp) # $ra をスタックに退避 la $t0, mydata # mydata のアドレスを読み込む lw $t1, 0($t0) # mydata の値を読み込む add $a0,$t1,$zero # mydata の値を (関数の引数として) $a0 に代入 jal fact # 関数 fact を呼び出す la $t0, S # S のアドレスを読み込む add $t2, $v0, $zero sw $v0, 0($t0) # 計算結果を S にストア lw $ra, 0($sp) # スタックに退避した $ra を元に戻す addi $sp,$sp,4 # スタックポインタを元に戻す jr $ra # end of program .globl fact fact: addi $sp, $sp, -8 #スタック上に2語文スペースを取る sw $ra, 4($sp) #戻りアドレスと引数を退避 sw $a0, 0($sp) slti $t0, $a0, 1 #n<1なら$t0=1に。 beq $t0, $zero, RECUR #n>=1ならRECURに分岐 addi $v0, $zero, 1 addi $sp, $sp, 8 #退避したけどやっぱりやめた。 jr $ra RECUR: addi $a0, $a0, -1 #引数をn-1にする jal fact #fact関数へ lw $a0, 0($sp) #復元する lw $ra, 4($sp) addi $sp, $sp, 8 #スタックを2語文おとす mul $v0, $a0, $v0 jr $ra
n = 3のとき。 $ra@e $ra@m $a0@3 $ra@3 $a0@2 $ra@2 $a0@1 $ra@1 $a0@0<-- //n = 0 で初めて分岐しなかった。 $ra@e $ra@m $a0@3 $ra@3 $a0@2 $ra@2 $a0@1<-- $v0=0+1 >| // lw $a0, 0($sp) #復元する // lw $ra, 4($sp) // addi $sp, $sp, 8 #スタックを2語文おとす // // mul $v0, $a0, $v0 // // jr $ra |< $ra@e $ra@m $a0@3 $ra@3 $a0@2<-- $v0 = $a0@1 * $v0@1 >| // lw $a0, 0($sp) #復元する // lw $ra, 4($sp) // addi $sp, $sp, 8 #スタックを2語文おとす // // mul $v0, $a0, $v0 // // jr $ra |< $ra@e $ra@m $a0@3<-- $v0 = $a0@2 * $v0@1 >| // lw $a0, 0($sp) #復元する // lw $ra, 4($sp) // addi $sp, $sp, 8 #スタックを2語文おとす // // mul $v0, $a0, $v0 // // jr $ra |< $ra@e<-- $v0 = $a0@3 * $v0@2 => $v0 = 6 //mainに戻る..