MIPS Assembly
Oct. 18th, 2009 01:41 pm![[personal profile]](https://www.dreamwidth.org/img/silk/identity/user.png)
Exercise:
Write a program for the SPIM simulator that uses `syscall' instruction to prompt the user to enter strings one per line representing valid decimal integers in the range from 0 to 999999999999. Use 64 bits for each integer. Valid strings may only contain the characters '0' through '9'. All strings other than valid decimal integers should be ignored. The numeric value indicated by each of the decimal strings should be added into a running 64-bit sum until a total of 10 strings have been entered or until the user indicates that there is no more input. The computed 64-bit sum should then be displayed on the console. This exercise involves converting between external and internal representation for input and between internal and external representation for output.
Solution:
.data prompt: .ascii "Please enter up to ten numbers from 0 to " .asciiz "999999999999, then type an empty line:\n" result: .asciiz "Sum is " newline: .asciiz "\n" buff: .space 25 special: .asciiz "09\n" .text .globl main main: la $t0, special lbu $s0, 0($t0) lbu $s1, 1($t0) lbu $s2, 2($t0) la $s3, buff li $s4, 10 move $s5, $zero move $s6, $zero move $s7, $zero # prompt to enter numbers li $v0, 4 la $a0, prompt syscall line: # read string li $v0, 8 move $a0, $s3 li $a1, 15 syscall # finish if an empty line is entered lb $t0, 0($s3) beq $t0, $s2, output # parse number move $a0, $s0 move $a1, $s1 move $a2, $s2 move $a3, $s3 jal atoi64 # add number to sum move $a0, $v0 move $a1, $v1 move $a2, $s6 move $a3, $s7 jal add64 move $s6, $v0 move $s7, $v1 # increment counter of strings addu $s5, $s5, 1 # finish if ten strings have been entered beq $s4, $s5, output # next line b line output: # format sum move $a0, $s0 la $a1, buff move $a2, $s6 move $a3, $s7 jal itoa64 # print sum li $v0, 4 la $a0, result syscall li $v0, 4 la $a0, buff syscall li $v0, 4 la $a0, newline syscall # exit li $v0, 10 syscall atoi64: subu $sp, $sp, 40 sd $s0, 0($sp) sd $s2, 8($sp) sd $s4, 16($sp) sd $s6, 24($sp) sw $ra, 32($sp) move $s0, $a0 move $s1, $a1 move $s2, $a2 move $s3, $a3 move $s4, $zero move $s5, $zero digit: lbu $s6, 0($s3) beq $s6, $s2, finish beqz $s6, finish # ignore strings including non-numeric characters bltu $s6, $s0, ignore bgtu $s6, $s1, ignore # translate character into digit subu $s7, $s6, $s0 addu $s3, $s3, 1 # multiply the accumulator by ten li $a0, 0 li $a1, 10 move $a2, $s4 move $a3, $s5 jal mult64 move $s4, $v0 move $s5, $v1 # add digit to the accumulator li $a0, 0 move $a1, $s7 move $a2, $s4 move $a3, $s5 jal add64 move $s4, $v0 move $s5, $v1 # next character b digit ignore: move $v0, $zero move $v1, $zero finish: ld $s0, 0($sp) ld $s2, 8($sp) ld $s4, 16($sp) ld $s6, 24($sp) lw $ra, 32($sp) addu $sp, $sp, 40 jr $ra itoa64: subu $sp, $sp, 40 sd $s0, 0($sp) sd $s2, 8($sp) sd $s4, 16($sp) sd $s6, 24($sp) sw $ra, 32($sp) move $s0, $a0 move $s1, $a1 move $s2, $a2 move $s3, $a3 move $s4, $s1 char: # divide number by ten move $a0, $s2 move $a1, $s3 li $a2, 10 jal div64 move $s2, $v0 move $s3, $v1 move $t0, $a3 # translate digit to character addu $t0, $t0, $s0 # write character sb $t0, 0($s1) # finish if quotient is zero seq $t0, $s2, $zero seq $t1, $s3, $zero and $t1, $t1, $t0 bnez $t1, return # move to the next position addu $s1, $s1, 1 b char return: # put null character to the end of the string move $t0, $zero sb $t0, 1($s1) # reverse the string move $a0, $s4 jal reverse ld $s0, 0($sp) ld $s2, 8($sp) ld $s4, 16($sp) ld $s6, 24($sp) lw $ra, 32($sp) addu $sp, $sp, 40 jr $ra reverse: # find the last character in the string move $t0, $a0 next: lbu $t1, 0($t0) beqz $t1, last addu $t0, $t0, 1 b next last: # move to the last character subu $t0, $t0, 1 swap: # done when pointers meet bgeu $a0, $t0, done # exchange characters lbu $t2, 0($a0) lbu $t3, 0($t0) sb $t2, 0($t0) sb $t3, 0($a0) # step to the next pair addu $a0, $a0, 1 subu $t0, $t0, 1 b swap done: jr $ra div64: divu $a0, $a2 mflo $a0 mfhi $a3 srl $t0, $a1, 16 sll $t1, $a3, 16 addu $t0, $t0, $t1 divu $t0, $a2 mflo $t0 mfhi $a3 andi $a1, $a1, 0xffff sll $t1, $a3, 16 addu $a1, $a1, $t1 divu $a1, $a2 mflo $a1 mfhi $a3 srl $t1, $t0, 16 addu $v0, $a0, $t1 sll $t1, $t0, 16 addu $v1, $a1, $t1 jr $ra mult64: multu $a1, $a3 mfhi $v0 mflo $v1 multu $a1, $a2 mflo $t0 addu $v0, $v0, $t0 multu $a0, $a3 mflo $t0 addu $v0, $v0, $t0 jr $ra add64: addu $v1, $a1, $a3 sltu $t0, $v1, $a1 addu $v0, $a0, $a2 addu $v0, $v0, $t0 jr $ra