Dayruiner
Dayruiner

Reputation: 1

MIPS/ MARS: Printing in Binary

This program contains main code at the beginning to call a subroutine called print_binary with three test numbers. Your job is to write print_binary. The end of print_binary is already written for you: it prints a new line and returns:

00000000000000000000000000000011

11111111111111111111111111111111

11001010111111101111000000001101

So far my output is:

00000000000000000000000000000000

10000000000000000000000000000000

10000000000000000000000000000000

It's important to note that I am not allowed to change main: and end:

I appreciate any help I can get on this,

Thanks,

   .text
main:
    li  $a0, 2
    jal print_binary
    li  $a0, -1
    jal print_binary
    li  $a0, 0xcafef00d
    jal print_binary

    li  $v0, 10             # exit
    syscall

# On entry, a0 = number to print in binary
print_binary:
    li $t1, 32               # Initialize a counter for the bit position (32 bits for unsigned)

loop:
    beqz $t1, end           # Exit the loop if all bits have been processed

    srl $t2, $a0, 31        # Get the most significant bit of the number
    andi $t2, $t2, 1        # Mask the least significant bit
    addi $t2, $t2, 48       # Convert the bit value to ASCII ('0' or '1')

    li $v0, 11              # syscall to print one char
    move $a0, $t2           # Load the bit value into $a0
    syscall

    sll $a0, $a0, 1         # Shift the original number to the left by 1 bit
    addiu $t1, $t1, -1      # Decrement the counter
    j loop

end:
    li $v0, 11              # syscall to print one char
    li $a0, 10              # Load newline character into $a0 ('\n')
    syscall
    jr $ra

Upvotes: 0

Views: 120

Answers (1)

Erik Eidt
Erik Eidt

Reputation: 26786

The problem is that you're expecting $a0 to hold its value, while your code to print a character wipes it out.  To make the syscall for printing a character, $a0 is necessarily repurposed, and the original value in it is lost.

li $v0, 11              # syscall to print one char
move $a0, $t2           # Load the bit value into $a0  <<--- overwrites $a0
syscall

You'll have find a way to preserve the value held in $a0 somehow.  There are several options.

  • Transfer (copy/move) to another register.  syscall is friendly and preserves all the registers except for the return value, if the syscall provides one — so you can move the value to $t3 at the beginning of your function and use it from there instead of from $a0.

  • Use some stack space — this approach would be necessary if you were calling another function instead of using syscall.

    There are two approaches to using some stack space to preserve this value:

    • Simply "push" (in the MIPS sense) the $a0 value to the stack and reload it from stack memory as needed during your loop, or,
    • "Push" an $s register to the stack and copy $a0 to that $s register and use that from there on.

    Either stack space approach will require you to allocate stack space, and deallocate prior to returning to the caller.


As a side note, you can observe that $a0 is wiped out of its former value during single step debugging of this.  When debugging assembly language code, it is useful to observe when registers change unexpectedly especially because of syscalls and/or function calls — though in this case it was your own code that overwrote the original parameter (in setting up the syscall), not the syscall itself.

Upvotes: 1

Related Questions