Reputation: 1
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
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:
$a0
value to the stack and reload it from stack memory as needed during your loop, or,$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