# Author:       Yee Hsu
# Filename:     "project2.s"
# Date:         3/22/98

# Description:  SAL/MAL program calculates sum of exponents giving by the
#               arrays of base numbers, powers, and number of terms 
#               entered by the user. Program contains nested funtion where
#               it calls sum_pow() and sum_pow() calls function pow().

                .data
#initialization
num_arr:        .word   0               # number of arrays
num_terms:      .word   0               # number of terms
power:          .word   0               # power to be raised
sum:            .word   0               # sum of powers
i:              .word   0               # counter

x:              .word   0:100           # int x[100] = {0};
ptr_x:          .word   0               # int *ptr_x = &x;

# cout prompts for inputs
prompt1:        .asciiz "Please enter number of items in array (< 100):"
prompt2:        .asciiz "Enter array items:\n"
prompt3:        .asciiz "Please enter a non-negative power (-1 to quit):"
prompt4:        .asciiz "Please enter the number of terms to sum:"

# cout outputs to the screen
output1:        .asciiz "Sum of "
output2:        .asciiz " array items to the power "
output3:        .asciiz " = "
output4:        .asciiz "\n\n"

                .text
__start:                                # main() {
        puts    prompt1                 # cout statement prompt 1
        get     num_arr                 # cin>>num_arr;

        puts    prompt2                 # cout statement prompt 2
        la      ptr_x, x                # ptr_x = &x;

for1:   get     M[ptr_x]                # for (i = 0; i < num_arr, i++) {
        add     ptr_x, ptr_x, 4         #       cin<<x[i];
        add     i, i, 1                 #       ptr_x++;
        blt     i, num_arr, for1        # }

        puts    prompt3                 # cout statement prompt 3
        get     power                   # cin>>power;

        beq     power, -1, end          # if (power == -1) then goto end
while:  puts    prompt4                 # while (power != -1)
        get     num_terms               # {
                                        #       cout statement prompt 4
        la      ptr_x, x                #       cin>>num_terms;
        lw      $a0, ptr_x              #       ptr_x = &x;
        lw      $a1, power
        lw      $a2, num_terms
        jal     sum_pow                 #       sum = sum_pow(x, power,
        sw      $v0, sum                #                    num_terms);

        puts    output1                 #       cout statement output 1
        put     num_terms               #       cout<<num_terms;
        puts    output2                 #       cout statement output 2
        put     power                   #       cout<<power;
        puts    output3                 #       cout statement output 3
        put     sum                     #       cout<<sum;
        puts    output4                 #       cout statement output 4
        puts    prompt3                 #       cout statement prompt 3
        get     power                   #       cin>>power;
        bne     power, -1, while        # } //end while
end:    done                            # } //end main()

# Function name: sum_pow()
# sum_pow() takes three arguments, x, power, and num_terms. The address of
# x is stored in arg0 and incremented by 4. sum_pow() calls function pow()
# passing argument *arg0 and power. Result is return when for loop is no
# longer true when counter is equal to num_terms.

#       Arguments
#       $a0     arg0    ptr_x
#       $a1     arg1    power
#       $a2     arg2    num_terms

#       Local Variables
#       $s0     i       loop counter
#       $s1     arg0    incrementation of ptr_x
#       $v0     result  result used to return back to main()
#       $v1             returned result from function pow()

# int sum_pow(int *arg0, int arg1, int arg2)
sum_pow:
        sw      $31, ($sp)              # push $31 on stack
        sw      $s0, -4($sp)            # push $s0 on stack
        sw      $s1, -8($sp)            # push $s1 on stack
        add     $sp, $sp, -12           # update stack pointer

        li      $s0, 0                  # int i = 0;
        li      $v0, 0                  # int result = 0;
        move    $s1, $a0                # arg0 = arg0;

for2:   lw      $a0, ($s1)              # for (i = 0, i < arg2, i++) {
        jal     pow                     #       temp = *arg0;
        add     $v0, $v0, $v1           #       result += pow(temp, arg1);
        add     $s1, $s1, 4             #       arg0++;
        add     $s0, $s0, 1             # }
        blt     $s0, $a2, for2

        add     $sp, $sp, 12            # update stack pointer
        lw      $s1, -8($sp)            # pop $s1 from stack
        lw      $s0, -4($sp)            # pop $s0 from stack
        lw      $31, ($sp)              # pop $31 from stack
        jr      $31                     # return result;

# Funtion name: pow()
# pow() accepts two arguments from function sum_pow(), arg0 and arg1.
# pow() calculates arg0 raised to the power of arg1. pow() returns result
# when for loop is no longer true when counter is equal to arg1.

#       Arguments
#       $a0     arg0    temp
#       $a1     arg1    power

#       Local Variables
#       $s0     i       loop counter
#       $v1     result  result used to return back to sum_pow()

# int pow(int arg0, int arg1)
pow:
        add     $sp, $sp, -4            # update stack pointer
        sw      $s0, 4($sp)             # push $s0 on stack

        li      $s0, 0                  # int i = 0;
        li      $v1, 1                  # int result = 1;

for3:   mul     $v1, $v1, $a0           # for (i = 0; i < arg1; i++) {
        add     $s0, $s0, 1             #       result *= arg0;
        blt     $s0, $a1, for3          # }

        add     $sp, $sp, 4             # update stack pointer
        lw      $s0, ($sp)              # pop $s0 from stack
        jr      $31                     # return result;