I currently am taking a course in assembly and am having trouble with the following assignment.
Write a program that reads (with an appropriate prompt) a sequence of 20 integers and stores them in an array, and then calls the following three functions and prints the results in a readable format.
The three functions are: smallestLargest: computes the smallest and the largest values in the array. divisible: computes the number of integers in the array which are divisible by 4 SumProduct: computes the sum and the product of the integers.
I wrote assembly code (below) to try to solve this problem but I can't get the right output except for the largest number in the array. Everything else is giving me a problem. I have no clue what's wrong, and I've been working on this for the past week and a half, so any help would be greatly appreciated.
.data
array: .space 80
newLine:.asciiz "\n" # I will use it to start a new line
space: .asciiz " " # I will use it to have a space
Prompt: .asciiz "\n Enter an integer: "
Result1:.asciiz "The smallest value in the array is "
Result2:.asciiz "The largest value in the array is "
Result3:.asciiz "The number of integers divisible by 4 is "
Result4:.asciiz "The sum of the integers is "
Result5:.asciiz "The product of the integers is "
.globl main
.text
main:
li $t0,20 # $t0 keeps track of the number of integers to be read
la $t1,array # loading the starting address of an array
loopQ:
la $a0,Prompt
li $v0,4
syscall
li $v0,5 # reading an integer
syscall
sw $v0,0($t1) # storing the integer entered
add $t0,$t0,-1 # decrement the number of integers by one
add $t1,$t1,4 # load the address of the next integer
bgtz $t0,loopQ # branch to read and store the next integer
li $t0,20
la $t1,array
smallestLargest:
lw $v0,0($t1) # $v0 = Mem($t1)
move $v1,$v0 # $v1 = $v0
addi $t0,$t0,-1 # decrement $t0
blez $t0,ret1 # while ($t0 > 0)
loopR:
addi $t1,$t1,4
lw $t2,0($t1) # load $t1 to $t2
bge $t2,$v0,next# if ($t2 < $v0)
move $v0,$t2 # $v0 = $t2
b chk
next:
ble $t2,$v1,chk # if ($t2 > $v1)
move $v1,$t2 # $v1 = $t2
chk:
addi $t0,$t0,-1 # decrement t0
bgtz $t0,loopR
ret1:
li $v0,4 # system call code for print_str
la $a0,Result1 # load address of Result1 into $a0
syscall
move $a0,$v0 # move value to be printed to $a0
li $v0,1 # system call code for print_int
syscall
la $a0,newLine # start a new line
li $v0,4
syscall
li $v0,4 # system call code for print_str
la $a0,Result2 # load address of Result2 into $a0
syscall
move $a0,$v1 # move value to be printed to $a0
li $v0,1 # system call code for print_int
syscall
la $a0,newLine # start a new line
li $v0,4
syscall
li $t0,20 # initialize length parameter
la $t1,array # initialize address parameter
Div4:
li $v0,0 # $v0 = 0
li $t3,3 # $t3 = 3
b skip
loopS:
lw $t2,0($t1) # $t2 = Mem($t1)
addi $t1,$t1,4 # $t1 = $t1 + 4
and $t4,$t2,$t3 # $t4 = $t2 & $t3
bnez $t4,skip # if ($t4 == 0)
addi $v0,$v0,1 # $v0 = $v0 + 1
skip:
addi $t0,$t0,-1 # $t0 = $t0 - 1
bgez $t0,loopS # if $t0 > 0
ret2:
li $v0,4 # system call code for print_str
la $a0,Result3 # load address of Result3 into $a0
syscall
move $a0,$v0 # move value to be printed to $a0
li $v0,1 # system call code for print_int
syscall
SumAMult:
la $a0,newLine # start a new line
li $v0,4
syscall
li $v0,4 # system call code for print_str
la $a0,Result4 # load address of Result4 into $a0
syscall
li $t0,20 # initialize length parameter
la $t1,array # initialize address parameter
jal sum # call sum
move $t1,$v0 # move value to be printed to $t1
li $v0,1 # system call code for print_int
syscall
la $a0,newLine # start a new line
li $v0,4
syscall
li $v0,4 # system call code for print_str
la $a0,Result5 # load address of Result5 into $a0
syscall
li $v0,1 # system call code for print_int
move $t1,$v1 # move value to be printed from $v1
syscall
li $v0,10
syscall
sum:
li $v0,0 # $v0 will hold the sum
li $v1,0 # $v1 will hold the product
loopT:
blez $t0, retzz # If t0 <= branch
addi $t0,$t0,-1 # decrement loop count
lw $t5,0($t1) # get a value from the array
addi $t1,$t1,4 # increment array pointer
word:
add $v0,$v0,$t5 # add to sum
# mult $v1,$t5 # multiply to product
b loopT # branch to loopT
retzz:
jr $ra
Below is the output I am getting after entering integers 1-20
The smallest value in the array is 4
The largest value in the array is 20
The number of integers divisible by 4 is 4
The sum of the integers is 268501210
The product of the integers is 268501238
I've fixed your code. I tried to remain faithful to it where possible, but, I had to do considerable restructuring.
A few things to note.
I created functions (per the problem statement). That is, instead of the equivalent of one long
main
, I split things up, just like you'd do in C. I added block comments for each function.In
main
, I loaded the array count into$s0
and the array base address into$s1
. The calculation functions set up their values from these rather than replicating the code. (i.e.) The array address and count can be set up/changed in one place, if desired.I changed some of the sidebar comments to be more descriptive of intent instead of merely restating the mechanics of the instruction they're on.
I also changed the labels so it was easier to match them to the functions they were in (e.g. all labels in function
foo
arefoo_blah
)I created static test data to speed up testing. Note the commented out
jal dataread
to actually prompt the user.Here's the corrected code:
Here's a more compact variation that uses a trick of sorts. It uses the equivalent of "tail call optimization" to have a common print routine instead of replicating the printing code in each calculation function.
That is, the "trick" is the calculation functions set up arguments for the print and then jump to it via
j
[instead of doing a second leveljal
] and the print function does thejr $ra
that would normally be done by the calculation functions.Anyway, here's the code:
Here's a C program that I used for comparison testing and validation:
Side note:
In addition to the
spim
simulator, there is themars
simulator. It can be found here: http://courses.missouristate.edu/KenVollmar/MARS/I've used both and prefer
mars
in most cases--YMMV