Creating a Single-Digit Adder using the MMIO Capabilities of MARS Simulator
.text
.globl main
main:
lui $t0,0xffff # load address of receiver control
lw $t1,0($t0) # load receiver control state
ori $t1,$t1,2 # enable keyboard interrupts
sw $t1,0($t0) # save receiver control state
loop:
b loop
li $v0, 10 # exit the program
syscall
.ktext 0x80000180 # location of exception/interrupt handler
la $k0,regspace
sw $t0,($k0) # save t0 value
sw $t1,4($k0) # save t1 value
sw $t2,8($k0) # save t2 value
sw $a0,12($k0) # save a0 value
sw $ra,16($k0) # save ra value
mfc0 $k0,$13 # load the cause register in k0
srl $t0,$k0, 2 # Extract exception code from $k0, bits 2-5
andi $t0,$t0, 0x1f
bnez $t0,skip # if not zero is not an interrupt
lui $t0,0xffff # load start address of I/O registers
lw $a0,4($t0) # load received character
la $t0,state
lw $t1,($t0) # load current state
beq $t1,0,state0
beq $t1,1,state1
beq $t1,2,state2
beq $t1,3,state3
state0:
blt $a0,'0',error # see if the char was a digit
bgt $a0,'9',error # if not, print error
li $t1,1 # go to state 1
sw $t1,($t0) # save state
la $t0,z
addi $t1,$a0,-48 # convert ascii to integer
sw $t1,($t0) # update total sum
b print # print current char
state1:
bne $a0,'+',error # see if the char was a plus sign, if not, print error
li $t1,2 # go to state 2
sw $t1,($t0) # save state
b print # print current char
state2:
blt $a0,'0',error # see if the char was a digit
bgt $a0,'9',error # if not, print error
li $t1,3 # go to state 3
sw $t1,($t0) # save state
la $t0,z
lw $t1,($t0) # load current sum
addi $t2,$a0,-48 # convert ascii to integer
add $t1,$t1,$t2 # add digit
sw $t1,($t0) # update total sum
b print # print current char
state3:
bne $a0,'=',error # see if the char was a plus sign, if not, print error
li $t1,0 # go to state 0 to start over
sw $t1,($t0) # save state
jal print_char # print equal sign
la $t0,z
lw $t1,($t0) # load current sum
blt $t1,10,onedig # if it's only one digit, print it
addi $t2,$t1,-10 # calculate remaining digit
li $a0,'1' # print first a one
jal print_char
move $t1,$t2
onedig:
addi $a0,$t1,48 # convert to ascii
jal print_char # print sum
li $a0,10 # to print a new line
b print
error:
li $t1,0 # go to state 0
sw $t1,($t0) # save state
li $a0,10 # to print a new line
jal print_char
li $a0,'E' # indicate error
jal print_char
li $a0,'R' # indicate error
jal print_char
li $a0,'R' # indicate error
jal print_char
li $a0,10 # to print a new line
print:
jal print_char
skip:
la $k0,regspace
lw $t0,($k0) # restore t0 value
lw $t1,4($k0) # restore t1 value
lw $t2,8($k0) # restore t2 value
lw $a0,12($k0) # restore a0 value
lw $ra,16($k0) # restore ra value
eret # return from exception
# print the character in a0
print_char:
lui $t0,0xffff # load start address of I/O registers
wait:
lw $t1,8($t0) # poll terminal status
andi $t1,$t1,1 # see if it's ready to transmit
beq $t1,$0,wait # if not, keep polling
sw $a0,12($t0) # send character to display
jr $ra
.kdata
regspace: .space 20 # space to save 5 registers
state: .word 0
z: .byte 0