4

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:

  1. Create space for 2 integer variables on the stack
  2. Initialize them to 5 and 10 respectively (for testing purposes)
  3. 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!

1 Answers1

0

This is a only a suggestion, not a firm answer, that you might not be calling printf with an address at all. I notice that after writing the address of the argument to the stack, you then revert the stack pointer before calling printf. So in both examples, the stack pointer is pointing to the original first argument when calling printf, which might explain why it prints the first argument in both cases.

sw      $t0, 0($sp)
lw      $t0, 0($sp)
nop
addiu   $sp, $sp, 4
...
# finally call printf
jalr    $t9
Weather Vane
  • 33,872
  • 7
  • 36
  • 56
  • My intention was to load the value at the address that I pop off the stack and into $t0. That's what the line "lw $5, 0($t0)" is supposed to do. I think I load the value off the stack and into $t0 before I increase the stack pointer. – Michael Stewart Apr 06 '15 at 21:44