[personal profile] codedot
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

Profile

Anton Salikhmetov

November 2018

S M T W T F S
    123
45678 910
11121314151617
18192021222324
252627282930 

Most Popular Tags

Style Credit

Expand Cut Tags

No cut tags
Page generated Aug. 11th, 2025 04:06 pm
Powered by Dreamwidth Studios