package main is body ma: integer; procedure a is -- proc level 1 begin aa,ab: integer; procedure b is -- proc level 2 begin ba: integer; procedure c is -- proc level 3 begin ca,cb: integer; begin ca := ba + 1; ma := ma + 1; writeln(" ca = ",ca," ma = ",ma); if ca <= -3 then writeln(" c calls a"); a; writeln(" ca = ",ca," ma = ",ma); end if; writeln(" return from c"); end; -- proc level 3 end begin ba := aa + 2; writeln(" ba = ",ba," and then b calls c"); c; writeln(" return from b: ba = ",ba); end; -- proc level 2 end begin aa := ma - 4; writeln(" aa = ",aa," and then a calls b"); b; writeln(" return from a: aa = ",aa); end; -- proc level 1 end begin ma := -2; writeln("ma = ",ma,"and then main calls a"); a; writeln("done in main: ma = ",ma); end;
# Register Usage: # $s0 for global variables # $s1 for level one procedure display # $s2 for level two procedure display # $s3 for level three procedure display # .text .globl main main: la $s0, VARS # # Start Code # Generate Assignment Statement # li $t0,-2 sw $t0,0($s0) # # Generate Writeln statement la $a0, S3 li $v0, 4 syscall li $v0, 1 lw $a0,0($s0) syscall la $a0, S2 li $v0, 4 syscall la $a0, S0 li $v0, 4 syscall jal L0 # jump to procedure a # # Generate Writeln statement la $a0, S1 li $v0, 4 syscall li $v0, 1 lw $a0,0($s0) syscall la $a0, S0 li $v0, 4 syscall # # Halt execution li $v0 10 syscall
# PROCEDURE HEADER # L1: # # Start of level 3 procedure c sw $ra, ($sp) # store return address sw $s3, -4($sp) # store old level 3 display move $s3, $sp # set new level 3 display to top of stack addi $sp, -16 # move by AR size
# BODY OF THE PROCEDURE # Generate Assignment Statement # lw $t0,-8($s2) add $t0,$t0,1 sw $t0,-8($s3) # Generate Assignment Statement # lw $t0,0($s0) add $t0,$t0,1 sw $t0,0($s0) # # Generate Writeln statement la $a0, S15 li $v0, 4 syscall li $v0, 1 lw $a0,-8($s3) syscall la $a0, S14 li $v0, 4 syscall li $v0, 1 lw $a0,0($s0) syscall la $a0, S0 li $v0, 4 syscall # # Generate If-Then statement lw $t1,-8($s3) li $t2,-3 sle $t1,$t1,$t2 beqz $t1,L3 # # Generate Writeln statement la $a0, S13 li $v0, 4 syscall la $a0, S0 li $v0, 4 syscall jal L0 # jump to procedure a # # Generate Writeln statement la $a0, S12 li $v0, 4 syscall li $v0, 1 lw $a0,-8($s3) syscall la $a0, S11 li $v0, 4 syscall li $v0, 1 lw $a0,0($s0) syscall la $a0, S0 li $v0, 4 syscall b L2 L3: L2: # # End If # # Generate Writeln statement la $a0, S10 li $v0, 4 syscall la $a0, S0 li $v0, 4 syscall
# END OF PROCEDURE addi $sp, 16 # move by AR size lw $s3, -4($sp) # restore old level 3display lw $ra, ($sp) # restore return address jr $ra # return # End of procedure c
# PROCEDURE HEADER L4: # # Start of level 2 procedure b sw $ra, ($sp) # store return address sw $s2, -4($sp) # store old level 2 display move $s2, $sp # set new level 2 display to top of stack addi $sp, -12 # move by AR size
# BODY OF PROCEDURE STATEMENTS # Generate Assignment Statement # lw $t0,-8($s1) add $t0,$t0,2 sw $t0,-8($s2) # # Generate Writeln statement la $a0, S9 li $v0, 4 syscall li $v0, 1 lw $a0,-8($s2) syscall la $a0, S8 li $v0, 4 syscall la $a0, S0 li $v0, 4 syscall jal L1 # jump to procedure c # # Generate Writeln statement la $a0, S7 li $v0, 4 syscall li $v0, 1 lw $a0,-8($s2) syscall la $a0, S0 li $v0, 4 syscall
# END OF PROCEDURE addi $sp, 12 # move by AR size lw $s2, -4($sp) # restore old level 2display lw $ra, ($sp) # restore return address jr $ra # return # End of procedure b
# HEADER OF PROCEDURE L0: # # Start of level 1 procedure a sw $ra, ($sp) # store return address sw $s1, -4($sp) # store old level 1 display move $s1, $sp # set new level 1 display to top of stack addi $sp, -16 # move by AR size
# BODY OF PROCEDURE # Generate Assignment Statement # lw $t0,0($s0) li $t1,4 sub $t0,$t0,$t1 sw $t0,-8($s1) # # Generate Writeln statement la $a0, S6 li $v0, 4 syscall li $v0, 1 lw $a0,-8($s1) syscall la $a0, S5 li $v0, 4 syscall la $a0, S0 li $v0, 4 syscall jal L4 # jump to procedure b # # Generate Writeln statement la $a0, S4 li $v0, 4 syscall li $v0, 1 lw $a0,-8($s1) syscall la $a0, S0 li $v0, 4 syscall
# END OF PROCEDURE addi $sp, 16 # move by AR size lw $s1, -4($sp) # restore old level 1display lw $ra, ($sp) # restore return address jr $ra # return # End of procedure a
# # Finish up by writing out constants .word 0 .data CONST: #Constant storage area S0: .asciiz "\n" S1: .asciiz "done in main: ma = " S2: .asciiz "and then main calls a" S3: .asciiz "ma = " S4: .asciiz " return from a: aa = " S5: .asciiz " and then a calls b" S6: .asciiz " aa = " S7: .asciiz " return from b: ba = " S8: .asciiz " and then b calls c" S9: .asciiz " ba = " S10: .asciiz " return from c" S11: .asciiz " ma = " S12: .asciiz " ca = " S13: .asciiz " c calls a" S14: .asciiz " ma = " S15: .asciiz " ca = " # # Reserve space for global variables .word 0 VARS: # space for Global Variables .data _ma: .word 0 # Offset at 0 ----------------------------------------------------------- Running the SPIM code
> spim SPIM Version 6.2 of January 11, 1999 Copyright 1990-1998 by James R. Larus (larus@cs.wisc.edu). All Rights Reserved. See the file README for a full copyright notice. Loaded: /opt/spim/bin/trap.handler (spim) load "p295.s" (spim) run ma = -2and then main calls a aa = -6 and then a calls b ba = -4 and then b calls c ca = -3 ma = -1 c calls a aa = -5 and then a calls b ba = -3 and then b calls c ca = -2 ma = 0 return from c return from b: ba = -3 return from a: aa = -5 ca = -3 ma = 0 return from c return from b: ba = -4 return from a: aa = -6 done in main: ma = 0 (spim) exit