Processing Null-Terminated Strings in MIPS Assembly
.data 0x10000100
.asciiz "Please enter first number: "
.data 0x10000120
.asciiz "Please enter second number: "
.data 0x10000140
.asciiz "Please enter third number: "
.data 0x10000160
.asciiz "Please enter fourth number: "
.data 0x10000180
.asciiz "Please enter fifth number: "
.text
.globl main
main:
lui $s0, 0x1000 # address of data
addi $a0, $s0, 0x100 # prompt for 1st number
addi $v0, $0, 4
syscall
addi $a0, $s0, 0
jal readNumber # read the number
sll $0, $0, 0
addi $a0, $s0, 0x120 # prompt for 2nd number
addi $v0, $0, 4
syscall
addi $a0, $s0, 0x8
jal readNumber # read the number
sll $0, $0, 0
addi $a0, $s0, 0x140 # prompt for 3rd number
addi $v0, $0, 4
syscall
addi $a0, $s0, 0x10
jal readNumber # read the number
sll $0, $0, 0
addi $a0, $s0, 0x160 # prompt for 4th number
addi $v0, $0, 4
syscall
addi $a0, $s0, 0x18
jal readNumber # read the number
sll $0, $0, 0
addi $a0, $s0, 0x180 # prompt for 5th number
addi $v0, $0, 4
syscall
addi $a0, $s0, 0x20
jal readNumber # read the number
sll $0, $0, 0
addi $v0, $0, 10 # exit the program
syscall
# readNumber: subroutine to read a numeric string from the user
# On entry: a0 = address to save read string
readNumber:
addi $v0, $0, 12 # read a character
syscall
ori $t0, $0, 0xa # if CR, end reading
beq $v0, $t0, endread
sll $0, $0, 0
ori $t0, $0, ',' # skip comma
beq $v0, $t0, skip
sll $0, $0, 0
ori $t0, $0, '+' # skip plus sign
beq $v0, $t0, skip
sll $0, $0, 0
sb $v0, 0($a0) # store character in string
addi $a0, $a0, 1 # advance to next position in string
skip:
j readNumber
sll $0, $0, 0
endread:
sb $0, 0($a0) # store and end of string
jr $ra
sll $0, $0, 0
.text
# average subroutine
.globl average
average:
addi $sp, $sp, -4 # allocate space in stack for a register
sw $ra, 0($sp) # save return address in stack
jal strToInt # convert first string to a number
sll $0, $0, 0
add $s0, $0, $v0
add $a0, $0, $a1 # convert second string to a number
jal strToInt
sll $0, $0, 0
add $s0, $s0, $v0 # accumulate sum
add $a0, $0, $a2 # convert third string to a number
jal strToInt
sll $0, $0, 0
add $s0, $s0, $v0 # accumulate sum
add $v0, $0, $s0 # return sum
addi $t0, $0, 3 # divide sum by 3 to get average
div $v0, $t0
mflo $a0
add $a1, $0, $a3 # save in third string
jal intToStr # convert number to a string
sll $0, $0, 0
lw $ra, 0($sp) # load return address from stack
sll $0, $0, 0
addi $sp, $sp, 4 # restore stack pointer
jr $ra
sll $0, $0, 0
# strToInt: subroutine to convert a string to a two's complement number
# On entry: a0 = string to convert
# On return: v0 = two's complement conversion
strToInt:
addi $v0, $0, 0
addi $t2, $0, 10
addi $t3, $0, 0 # t3 is 1 if the string is negative
lb $t0, 0, ($a0) # load character from string
sll $0, $0, 0
addi $t1, $0, '-' # see if it's a negative number
bne $t0, $t1, cnvloop # if not, start conversion
sll $0, $0, 0
addi $a0, $a0, 1 # skip sign
addi $t3, $0, 1 # t3 is 1, string is negative
cnvloop:
lb $t0, 0, ($a0) # load character from string
sll $0, $0, 0
beq $t0, $0, endcnv # if it's end of string, we finished the conversion
sll $0, $0, 0
addi $t0, $t0, -48 # else, should be a digit, convert ascii to a number
mult $v0, $t2 # multiply old number by 10
mflo $v0
add $v0, $v0, $t0 # add digit
addi $a0, $a0, 1 # advance to next char in string
j cnvloop # repeat
sll $0, $0, 0
endcnv:
beq $t3, $0, retcnv # if the number was positive, return it
sll $0, $0, 0
lui $t0, 0xFFFF
ori $t0, 0xFFFF
xor $v0, $v0, $t0 # invert number (one's complement)
addi $v0, $v0, 1 # add 1 to get two's complement
retcnv:
jr $ra
sll $0, $0, 0
# intToStr: subroutine to convert a two's complement number to a string
# On entry: a0 = number to convert, a1 = string to save the conversion
intToStr:
slt $t0, $a0, $0 # see if the number is negative
beq $t0, $0, positive # if not, go to positive
sll $0, $0, 0
addi $t0, $0, '-' # save a negative sign in string
sb $t0, 0, ($a1)
addi $a1, $a1, 1 # advance to next position
lui $t0, 0xFFFF
ori $t0, 0xFFFF
xor $a0, $a0, $t0 # invert number (one's complement)
addi $a0, $a0, 1 # add 1 to get positive two's complement number
positive:
addi $t2, $0, 10
addi $sp, $sp, -1
sb $t2, 0($sp) # save a 10 at top of stack
divloop:
div $a0, $t2 # divide number by 10
mflo $a0
mfhi $t0 # get remainder in $t0
addi $sp, $sp, -1
sb $t0, 0($sp) # save digit in stack
bne $a0, $0, divloop # repeat until the number is zero
sll $0, $0, 0
savecnv:
lb $t0, 0($sp) # load digit from stack
sll $0, $0, 0
addi $sp, $sp, 1
beq $t0, $t2, cnvdone # if we reached the last digit, end conversion
sll $0, $0, 0
addi $t0, $t0, '0' # else, convert digit to ascii
sb $t0, 0($a1) # save in string
addi $a1, $a1, 1 # advance to next position in string
j savecnv # repeat
sll $0, $0, 0
cnvdone:
jr $ra
sll $0, $0, 0
.text
# sort: sorting subroutine
.globl sort
sort:
addi $sp, $sp, -20 # allocate space in stack for 5 registers
sw $ra, 0($sp) # save return address in stack
sw $s0, 4($sp) # save $s0 in stack
sw $s1, 8($sp) # save $s1 in stack
sw $s2,12($sp) # save $s2 in stack
sw $s3,16($sp) # save $s3 in stack
lui $s0, 0x1000 # start address of data
addi $s1, $0, 4 # counter for fist loop (i)
loop1:
add $s2, $0, $s1 # counter for inner loop (j)
addi $s3, $s0, 8 # pointer to num[i+1]
loop2:
add $a0, $0, $s0 # get num[i]
add $a1, $0, $s3 # get num[j]
jal compare
sll $0, $0, 0
beq $v0, $0, next # if num[i] <= num[j], goto next
sll $0, $0, 0
slt $t0, $v0, $0
bne $t0, $0, next
sll $0, $0, 0
lw $t0, 0($s0) # else, swap strings
sll $0, $0, 0
lw $t1, 4($s0)
sll $0, $0, 0
lw $t2, 0($s3)
sll $0, $0, 0
lw $t3, 4($s3)
sll $0, $0, 0
sw $t0, 0($s3)
sw $t1, 4($s3)
sw $t2, 0($s0)
sw $t3, 4($s0)
next:
addi $s3, $s3, 8 # advance to next element
addi $s2, $s2, -1 # decrement inner loop counter
bne $s2, $0, loop2
sll $0, $0, 0
addi $s0, $s0, 8 # advance to next element
addi $s1, $s1, -1 # decrement outer loop counter
bne $s1, $0, loop1
sll $0, $0, 0
lw $ra, 0($sp) # load return address from stack
sll $0, $0, 0
lw $s0, 4($sp) # load $s0 from stack
sll $0, $0, 0
lw $s1, 8($sp) # load $s1 from stack
sll $0, $0, 0
lw $s2,12($sp) # load $s2 from stack
sll $0, $0, 0
lw $s3,16($sp) # load $s3 from stack
sll $0, $0, 0
addi $sp, $sp, 20 # restore stack pointer
jr $ra
sll $0, $0, 0
# compare: subroutine to compare two strings as integers
# on entry: $a0: address of first string, a1: address of second string
# On return: $v0: comparison result (<0 if str10 if str1>str2)
compare:
addi $sp, $sp, -8 # allocate space in stack for 2 registers
sw $ra, 0($sp) # save return address in stack
sw $s0, 4($sp) # save $s0 in stack
jal strToInt # convert first string to int
sll $0, $0, 0
add $s0, $0, $v0 # save result in s0
add $a0, $0, $a1
jal strToInt # convert second string to int
sll $0, $0, 0
sub $v0, $s0, $v0 # make comparison
lw $ra, 0($sp) # load return address from stack
sll $0, $0, 0
lw $s0, 4($sp) # load $s0 from stack
sll $0, $0, 0
addi $sp, $sp, 8 # restore stack pointer
jr $ra
sll $0, $0, 0
# strToInt: subroutine to convert a string to a two's complement number
# On entry: a0 = string to convert
# On return: v0 = two's complement conversion
strToInt:
addi $v0, $0, 0
addi $t2, $0, 10
addi $t3, $0, 0 # t3 is 1 if the string is negative
lb $t0, 0, ($a0) # load character from string
sll $0, $0, 0
addi $t1, $0, '-' # see if it's a negative number
bne $t0, $t1, cnvloop # if not, start conversion
sll $0, $0, 0
addi $a0, $a0, 1 # skip sign
addi $t3, $0, 1 # t3 is 1, string is negative
cnvloop:
lb $t0, 0, ($a0) # load character from string
sll $0, $0, 0
beq $t0, $0, endcnv # if it's end of string, we finished the conversion
sll $0, $0, 0
addi $t0, $t0, -48 # else, should be a digit, convert ascii to a number
mult $v0, $t2 # multiply old number by 10
mflo $v0
add $v0, $v0, $t0 # add digit
addi $a0, $a0, 1 # advance to next char in string
j cnvloop # repeat
sll $0, $0, 0
endcnv:
beq $t3, $0, retcnv # if the number was positive, return it
sll $0, $0, 0
lui $t0, 0xFFFF
ori $t0, 0xFFFF
xor $v0, $v0, $t0 # invert number (one's complement)
addi $v0, $v0, 1 # add 1 to get two's complement
retcnv:
jr $ra
sll $0, $0, 0