Đệ quy trong MIPS
Để thực hiện được đệ quy trong MIPS, điều quan tâm của chúng ta là các kết quả trung gian và thanh ghi địa chỉ $ra. MIPS cung cấp cho chúng ta một stack pointer (thanh ghi $sp). Theo cơ chế stack thì cứ trước mỗi lần gọi thì ta giảm giá trị của thanh $sp, sau đó Push vào các kết quả trung gian cần nhớ và thanh ghi $ra. Sau lời gọi đệ quy thì ta lấy lại các kết quả trung gian xử lí tính toán và phục hồi lại thanh $ra, sau đó jr $ra là OK!
Nguyên nhân tại sao lại lưu thanh ghi $ra: Khi ta gọi thủ tục jal [ten-thu-tuc], thì lúc đó thanh ghi $ra tự động cập nhật lại địa chỉ phái sau lệnh jal, để chương trình sau khi thực hiện xong thủ tục thì chạy về thủ tục gọi hàm và thực hiện tiếp những lệnh sau nó. Khi đệ quy, tức là gọi lại thủ tục đó nhiều lần, nếu như ta không lưu lại thanh ghi $ra thì $ra sẽ được cập nhật mới sau mỗi lần gọi đệ quy. Vì thế nó sẽ không nhớ được đường về những lần gọi thủ tục trước lần gọi cuối cùng.
Và sau đây là một bài code mẫu tính giai thừa bằng đệ quy:
Nguyên nhân tại sao lại lưu thanh ghi $ra: Khi ta gọi thủ tục jal [ten-thu-tuc], thì lúc đó thanh ghi $ra tự động cập nhật lại địa chỉ phái sau lệnh jal, để chương trình sau khi thực hiện xong thủ tục thì chạy về thủ tục gọi hàm và thực hiện tiếp những lệnh sau nó. Khi đệ quy, tức là gọi lại thủ tục đó nhiều lần, nếu như ta không lưu lại thanh ghi $ra thì $ra sẽ được cập nhật mới sau mỗi lần gọi đệ quy. Vì thế nó sẽ không nhớ được đường về những lần gọi thủ tục trước lần gọi cuối cùng.
Và sau đây là một bài code mẫu tính giai thừa bằng đệ quy:
.data
st_Nhap: .asciiz "Nhap vao so n: "
.text
main:
addi $v0 $0, 5
syscall
addi $a0, $v0, 0
jal giaithua
addi $a0, $v0, 0
addi $v0 $0, 1
syscall
addi $v0 $0, 10
syscall
giaithua: # <=> $v0 = giaithua($a0)
bne $a0, $0 , dequy
addi $v0, $0, 1
jr $ra
dequy:
addi $sp, $sp, -8
sw $a0, 0($sp)
sw $ra, 4($sp)
addi $a0, $a0, -1
jal giaithua
lw $a0, 0($sp)
addi $a1, $v0, 0
jal Nhan
lw $ra, 4($sp)
addi $sp, $sp, 8
jr $ra
Nhan:
addi $sp, $sp, -4
sw $ra, 0($sp)
addi $v0, $0, 0
LapNhan:
slt $t0, $0, $a1
beq $t0, $0, KTLapNhan
add $v0, $v0, $a0
addi $a1, $a1, -1
j LapNhan
KTLapNhan:
lw $ra, 0($sp)
addi $sp, $sp, 4
jr $ra
Nhận xét
Đăng nhận xét