5.10 Gọi hàm dùng stack
Các chú ý khi một thủ tục gọi một thủ tục con dùng stack:
Thiết lập các tham số trong menu Simulator -> Settings:
Bare Machine OFF, Allow Pseudo Instructions ON, Load Trap File ON, Delayed
Branches ON, Delayed Loads ON, Mapped IO ON, Quiet OFF.
Sau đây là ví dụ chương trình yêu cầu người dùng nhập vào 2 số X, Y. Chương trình thực
hiện việc tính toán các biểu thức X*X, X*Y, 5*Y và in ra kết quả lớn nhất từ giá trị của 3
biểu thức trên. Chương trình main gọi thủ tục con maxExp tính và tìm ra giá trị lớn nhất
từ ba biểu thức X*X, X*Y và 5*Y sau khi đã có giá trị X, Y. Thủ tục con maxExp gọi
thủ tục con maxInt hai lần để so sánh X*X với X*Y, kết quả sẽ so sánh với 5*Y để cho ra
kết quả yêu cầu.
Gọi thủ tục con
(thực hiện bởi chương trình gọi):
1. Push vào stack các thanh ghi $t0-$t9 cần lưu giá trị. Thủ tục con có thể thay đổi các
thanh ghi này.
2. Gán giá trị vào các tham số của thủ tục con $a0-$a3.
3. Gọi thủ tục con sử dụng jal.
Phần đầu thủ tục con
(Trong thủ tục con):
4. Nếu thủ tục con này có thể gọi các thủ tục con khác, phải push $ra vào stack.
5. Push vào stack các thanh ghi $s0-$s7 nếu thủ tục con này có thể thay đổi chúng.
Thân thủ tục con:
6. Thủ tục con có thể thay đổi các thanh ghi T, A hoặc S (nếu như S đã được lưu ở bước 5).
7. Nếu thủ tục con này gọi thủ tục con khác thì nó phải tuân thủ các chú ý này.
Phần cuối thủ tục con
(Thực hiện trước khi trở về chương trình gọi):
8. Đưa các giá trị cần trả về vào $v0-$v1
9. Pop ra khỏi stack (theo thứ tự ngược) các thanh ghi $s0-$s7 đã lưu ở bước 5.
10. Pop ra khỏi stack địa chỉ trở về $ra nếu thực hiện bước 4
11. Trở về chương trình gọi sử dụng jr $ra.
Phục hồi điều khiển
sau khi trở về từ chương trình con (thực hiện bởi chương trình gọi):
12. Pop ra khỏi stack (theo thứ tự ngươc) các thanh ghi $t0-$t9 đã được push vào stack
ở bước 1.
## Driver -- main program for the application
.text
.globl main
main:
sub $sp,$sp,4 # push the return address
sw $ra,($sp)
sub $sp,$sp,4 # push $s0
sw $s0,($sp)
la $a0,xprompt # prompt the user
li $v0,4 # service 4
syscall
li $v0,5 # service 5 -- read int
syscall # $v0 = integer
move $s0,$v0 # save x
la $a0,yprompt # prompt the user
li $v0,4 # service 4
syscall
li $v0,5 # service 5 -- read int
syscall # $v0 = integer
# prepare arguments
move $a0,$s0 # x
move $a1,$v0 # y
jal maxExp # maximum expression
nop # returned in $v0
move $s0,$v0 # keep it safe
la $a0,rprompt # output title
li $v0,4 # service 4
syscall
move $a0,$s0 # get maximum
li $v0,1 # print it out
syscall
lw $ra,($sp) # pop $s0
add $s0,$sp,4
lw $ra,($sp) # pop return address
add $sp,$sp,4
jr $ra # return to OS
nop
.data
xprompt: .asciiz "Enter a value for x --> "
yprompt: .asciiz "Enter a value for y --> "
rprompt: .asciiz "The maximum expression is: "
## maxInt -- compute the maximum of two integer arguments
##
## Input:
## $a0 -- a signed integer
## $a1 -- a signed integer
##
## Returns:
## $v0 -- maximum
.text
.globl maxInt
maxInt:
# body
move $v0,$a0 # max = $a0
bgt $a0,$a1,endif # if $a1 > $a0
nop
move $v0,$a1 # max = $a1
endif: # endif
# epilog
jr $ra # return to caller
nop
## maxExp -- compute the maximum of three expressions
##
## Input:
## $a0 -- a signed integer, x
## $a1 -- a signed integer, y
##
## Returns:
## $v0 -- the maximum of x*x, x*y, or 5*y
##
## Registers:
## $s0 -- x*x
## $s1 -- x*y
## $s2 -- 5*y
.text
.globl maxInt
maxExp:
# prolog
sub $sp,$sp,4 # push the return address
sw $ra,($sp)
sub $sp,$sp,4 # push $s0
sw $s0,($sp)
sub $sp,$sp,4 # push $s1
sw $s1,($sp)
sub $sp,$sp,4 # push $s2
sw $s2,($sp)
# body
mul $s0,$a0,$a0 # x*x
mul $s1,$a0,$a1 # x*y
li $t0,5
mul $s2,$t0,$a1 # 5*y
move $a0,$s0 # compute max of x*x
move $a1,$s1 # and x*y
jal maxInt # current max in $v0
nop
move $a0,$v0 # compute max of
move $a1,$s2 # current max, and 5*y
jal maxInt # total max will be in $v0
nop
Chia sẻ với bạn bè của bạn: |