嵌套過程
不調用其他過程的過程稱為葉過程(leaf procedure)。如果所有過程都是葉過程,那么情況就很簡單。但是某個過程可以調用其他過程,甚至調用的是自身的“克隆”。在調用非葉過程時使用寄存器需要十分小心。
例如,假設主程序將參數3存入寄存器a0,然后使用jal A調用過程A。再假設過程A通過jal B調用過程B,參數為7,同樣存入a0。由於A尚未結束任務,所以在寄存器a0的使用上存在沖突。同樣,在寄存器ra保存的返回地址也存在沖突,因為它現在保存着B的返回值。
我們必須采取措施阻止這類問題發生:
一個解決方法是將其他所有必須保存的寄存器壓棧,就像將保存寄存器壓棧一樣。調用者將所有調用后還需的參數寄存器(a1~a3)或臨時寄存器(t0~t9)壓棧。被調用者將返回地址寄存器(ra)和被調用者使用的保存寄存器(a0~a7)都壓棧。棧指針 sp 隨這棧中的寄存器個數調整。到返回時,寄存器會從存儲器中恢復,棧指針也會隨着重新調整。
有關指令
1 jal function #set $ra to Program Counter(PC),then jump to statement at target addres
C語言代碼
1 #include<stdio.h> 2 3 int factorial(int n); 4 5 int main() 6 { 7 int n; 8 scanf("%d", &n); 9 int res = factorial(n); 10 printf("%d\n",res); 11 return 0; 12 } 13 14 int factorial(int n) 15 { 16 if (n < 1) return 1; 17 else return n * factorial(n - 1); 18 }
雖然在C語言中函數定義可以在main函數前,也可以在main函數后,但定義在main函數后似乎更接近MIPS風格(看下面的代碼你就知道了)
MIPS代碼
1 .data 2 prompt1: .asciiz "Enter the number\n" 3 prompt2: .asciiz "The factorial of n is:\n" 4 5 .text 6 # Print prompt1 7 li $v0, 4 8 la $a0, prompt1 9 syscall 10 11 # Read integer 12 li $v0, 5 13 syscall 14 15 # Call factorial 16 move $a0, $v0 17 jal factorial 18 move $a1, $v0 # save return value to a1 19 20 # Print prompt2 21 li $v0, 4 22 la $a0, prompt2 23 syscall 24 25 # Print result 26 li $v0, 1 27 move $a0, $a1 28 syscall 29 30 # Exit 31 li $v0, 10 32 syscall 33 34 ## Function int factorial(int n) 35 factorial: 36 ## YOUR CODE HERE 37 addi $sp,$sp,-8 #adjust stack for 2 items 38 sw $ra,4($sp) #save return address 39 sw $a0,0($sp) #save the argument n 40 41 slti $t0,$a0,1 #if n < 1,then set $t0 as 1 42 beq $t0,$zero,L1 #if equal,then jump L1 43 #above all,if n >= 1,then jump L1 44 #if(n < 1) 45 addi $v0,$zero,1 #return 1 46 addi $sp,$sp,8 #pop 2 items off stack 47 jr $ra #return to caller 48 #else 49 L1: 50 add $a0,$a0,-1 #argument :n - 1 51 jal factorial #call factorial with (n-1) 52 53 lw $a0,0($sp) #restore argument n 54 lw $ra,4($sp) #restore address 55 addi $sp,$sp,8 #adjust stack pionter 56 mul $v0,$a0,$v0 #return n * factorial(n-1) 57 jr $ra return to caller 58 ## END OF YOUR CODE 59 #jr $ra
手繪調用棧: