Why is my MIPS base converter printing out the values from a previous loop after the current values?
Solution 1:
The strings you print with syscall 4 need to be ASCIIZ, i.e. ASCII with a zero terminator. So you need to store a byte with the value zero after the last character in each string. And to be able to store that extra byte, you need to reserve one additional byte for each string (i.e. .space 33
for binResult
, etc).
Actually, just increasing the number of bytes reserved with .space
should be enough, as .space
should zero-initialize the memory. But adding an extra sb
per string just to be sure wouldn't hurt much.
Solution 2:
I had some difficulty making sense of all the code with some conflicting comments and register usage (e.g. enter 27 and hex comes back 0). When I ran it, stepping through it, I think I saw the rol
trash things. Dunno for sure as I only ran it once or twice.
So, I did a recode using a different method. The code for all four bases is now common. I did the hex and octal. I left the base 4 and base 2 for you to do.
Anyway, here's the code [please pardon the gratuitous style cleanup]:
.text
.globl main
main:
la $a0,prompt # Prompt for a base10 integer
li $v0,4
syscall
# get the value
li $v0,5
syscall
move $s7,$v0
###jal bin
###jal base4
jal hex
jal oct
la $a0,endl
li $v0,4
syscall
la $a0,repeat
li $v0,4
syscall
li $v0,5
syscall
beqz $v0,eop
la $a0,endl
li $v0,4
syscall
j main
eop:
li $v0,10 # End Of Program
syscall
# BASE 16
hex:
la $a0,hexmsg # Display string before hex answer
li $a1,0x0F # mask for hex digit
li $a2,28 # initial right shift amount
li $a3,4 # right shift decrement
j numdump
# BASE 8
oct:
la $a0,octmsg # Display string before hex answer
li $a1,0x07 # mask for octal digit
li $a2,30 # right shift amount
li $a3,3 # right shift decrement
j numdump
# numdump -- dump out a number in an alternate base
#
# arguments:
# a0 -- pointer to string for prefix
# a1 -- mask for digit
# a2 -- initial right shift amount
# a3 -- amount to decrement shift by
# s7 -- number value
numdump:
li $v0,4
syscall
la $t3,result # output string set up here
numloop:
srlv $t0,$s7,$a2 # slide the digit right
and $t0,$t0,$a1 # mask the digit
lb $t0,digits($t0) # get the ascii value
sb $t0,0($t3) # store into result buffer
addi $t3,$t3,1 # advance result pointer
sub $a2,$a2,$a3 # reduce shift amount -- more to do?
bgez $a2,numloop # yes, loop
sb $zero,0($t3) # store end of string
la $a0,result # display result
li $v0,4
syscall
la $a0,endl
syscall
jr $ra # Return
.data
result: .space 40
digits: .asciiz "0123456789ABCDEF"
endl: .asciiz "\n"
prompt: .asciiz "Enter a decimal number: "
b2msg: .asciiz "The number in base 2 is "
b4msg: .asciiz "The number in base 4 is "
hexmsg: .asciiz "The number in base 16 is "
octmsg: .asciiz "The number in base 8 is "
repeat: .asciiz "Would you like to input another number? "
Here's a slightly more compact version that requires one less argument to the common function:
.text
.globl main
main:
la $a0,prompt # Prompt for a base10 integer
li $v0,4
syscall
# get the value
li $v0,5
syscall
move $s7,$v0
###jal bin
###jal base4
jal hex
jal oct
la $a0,endl
li $v0,4
syscall
la $a0,repeat
li $v0,4
syscall
li $v0,5
syscall
beqz $v0,eop
la $a0,endl
li $v0,4
syscall
j main
eop:
li $v0,10 # End Of Program
syscall
# BASE 16
hex:
la $a0,hexmsg # Display string before hex answer
li $a1,4 # number of bits in a digit
li $a2,28 # initial right shift amount
j numdump
# BASE 8
oct:
la $a0,octmsg # Display string before hex answer
li $a1,3 # number of bits in a digit
li $a2,30 # right shift amount
j numdump
# numdump -- dump out a number in an alternate base
#
# arguments:
# a0 -- pointer to string for prefix
# a1 -- number of bits in a digit
# a2 -- initial right shift amount
# s7 -- number value
#
# registers:
# a3 -- digit mask
numdump:
li $v0,4
syscall
la $t3,result # output string set up here
# create digit mask from number of bits in a digit
li $a3,1 # mask = 1
sllv $a3,$a3,$a1 # mask <<= digit width (for hex, 0x10)
subiu $a3,$a3,1 # bump down for mask (for hex, 0x0F)
numloop:
srlv $t0,$s7,$a2 # slide the digit right
and $t0,$t0,$a3 # mask the digit
lb $t0,digits($t0) # get the ascii value
sb $t0,0($t3) # store into result buffer
addi $t3,$t3,1 # advance result pointer
sub $a2,$a2,$a1 # reduce shift amount -- more to do?
bgez $a2,numloop # yes, loop
sb $zero,0($t3) # store end of string
la $a0,result # display result
li $v0,4
syscall
la $a0,endl
syscall
jr $ra # Return
.data
result: .space 40
digits: .asciiz "0123456789ABCDEF"
endl: .asciiz "\n"
prompt: .asciiz "Enter a decimal number: "
b2msg: .asciiz "The number in base 2 is "
b4msg: .asciiz "The number in base 4 is "
hexmsg: .asciiz "The number in base 16 is "
octmsg: .asciiz "The number in base 8 is "
repeat: .asciiz "Would you like to input another number? "