I am working on an assignment for my compilers course and I've been staring at the mips (32 bit) code I generate for hours trying to figure out what is wrong with it to no avail. After generating the mips code, I compile it using gcc on a mips VM provided by our instructor. I was told to make use of some C stdlib functions like printf and I'm pretty sure that part of the code is correct since (as we were instructed to do) I mostly stole it from gcc's output of similar C code.
Below is the mips code which should:
- Create space for 2 integer variables on the stack
- Initialize them to 5 and 10 respectively (for testing purposes)
- Print both of them out by pushing their absolute addresses onto the stack and then popping it off and accessing it.
At the moment what happens is the second printf appears to print the value stored in the first variable's space on the stack rather than the second variable's value.
(the code fully works when using constant ints so I believe the printf's are completely correct)
.data
printf_string: .asciiz "%d\n"
scanf_string: .asciiz "%d"
.text
.globl main
main:
# make space for two ints on stack
addiu $sp, $sp, -8
# store return address in a saved register
# was going to push it onto the stack but until I figure out this issue I'm
# being lazy and just saving it to a saved register
move $s0, $ra
# make a copy of the stack pointer - likely not needed
move $s1, $sp
# typically here i loop and initialize the 2 ints on the stack but for now I'm
# doing it manually so I can figure out this issue with less possible things
# that could be wrong
# load some value into the register so I can store it
li $t7, 5
# store into first variable
sw $t7, 0($sp)
# different so I can tell if printing location works
li $t7, 10
# store into second variable
sw %t7, 4($sp)
instructions:
########################################
### CODE BELOW PRINTS FIRST VARIABLE ###
########################################
# appears to work...
# load standard library pointer and stuff (copied from gcc output)
# everything below works IF you did something like
# "WRITE 5" instead of "WRITE a"
lui $gp, %hi(__gnu_local_gp)
addiu $gp, %lo(__gnu_local_gp)
lw $t9, %call16(printf)($gp)
.cprestore 16
nop # needed after load word :-/
# load print_string address - works
la $4, printf_string
# Here's where problems start
# make space for location of visited variable
addiu $sp, $sp, -4
# initialize $t0 to top of stack
move $t0, $s1
# add offset of variable to $t0
addiu $t0, $t0, 0
# store absolute memory address of variable to stack
sw $t0, 0($sp)
# load absolute memory address of variable from stack
lw $t0, 0($sp)
nop # needed after lw
# undo stack allocation
addiu $sp, $sp, 4
# load MEM[$t0 + 0] into $5 (arg 2)
lw $5, 0($t0)
nop
# finally call printf
jalr $t9
nop
#########################################
### CODE BELOW PRINTS SECOND VARIABLE ###
#########################################
# appears to print the value stored in the first variable
# if I add "sw $s5, 4($sp)" here then it DOES work so I'm just very confused
# everything here should be basically the same as above but with a different
# offset/address pushed, popped, and accessed
lui $gp, %hi(__gnu_local_gp)
addiu $gp, %lo(__gnu_local_gp)
lw $t9, %call16(printf)($gp)
.cprestore 16
nop
la $4, printf_string
addiu $sp, $sp, -4
move $t0, $s1
addiu $t0, $t0, 4
sw $t0, 0($sp)
lw $t0, 0($sp)
nop
addiu $sp, $sp, 4
lw $5, 0($t0)
nop
jalr $t9
nop
addiu $sp, $sp, 8
move $ra, $s0
jr $ra
nop
If anyone could find anything that even appears to be off then I would greatly appreciate it!