Academic Integrity: tutoring, explanations, and feedback — we don’t complete graded work or submit on a student’s behalf.

#*******************************************************************************

ID: 3862500 • Letter: #

Question

#****************************************************************************************

# FILE: h3-2.s

#

# DESCRIPTION

# CSE/EEE 230 Spring 2017 Homework Assignment 3, Exercise 6

#

# AUTHOR

# <your-name>           (<your-email-address>)

# <your-partner's-name> (<your-partner's-email-address>)

#****************************************************************************************

#========================================================================================

# Equivalents for MARS System Calls

#========================================================================================

.eqv SYS_EXIT          10

.eqv SYS_PRINT_CHAR    11

.eqv SYS_PRINT_INT      1

.eqv SYS_PRINT_STR      4

.eqv SYS_RAND_INT_RNG 42

.eqv SYS_READ_INT       5

.eqv SYS_SET_SEED      40

#========================================================================================

# Data Section

#

# Contains global data for the program.

#========================================================================================

.data

s_neg:      .asciiz "Number of negative ints: "

s_nonneg:   .asciiz "Number of non-negative ints: "

#========================================================================================

# Text Section

#

# Contains instructions for the program.

#========================================================================================

.text

#----------------------------------------------------------------------------------------

# main() - Allocates an array of 128 ints, fills it up with random integers in [-500,

# 500], and calls count() which returns the number of negative and non-negative ints.

# Displays the two counts and then terminates.

#

# PSEUDOCODE

# function main ()

#     int a[128], i, neg, nonneg

#     SysSetSeed (1, 1234)

#     for i = 0 to 127 do

#         a[i] = SysRandInt (1, 1000) - 500 -- generates random integers in [-500, 500]

#     end for

#     neg, nonneg = count (a)

#     SysPrintStr ("Number of negative ints: ")

#     SysReadInt (neg)

#     SysPrintChar (' ')

#     SysPrintStr ("Number of non-negative ints: ")

#     SysReadInt (nonneg)

#     SysPrintChar (' ')

#     SysExit ()

# end function main

#

# The following pseudocode is main() rewritten to convert the for loop into a while

# loop,

#

# function main ()

#     int a[128], i, neg, nonneg

#     SysSetSeed (1, 1234)

#     i = 0

#     while i <= 127 do

#         a[i] = SysRandInt (1, 1000) - 500 -- generates random integers in [-500, 500]

#         i = i + 1

#     end while

#     neg, nonneg = count (a)

#     SysPrintStr ("Number of negative ints: ")

#     SysReadInt (neg)

#     SysPrintChar (' ')

#     SysPrintStr ("Number of non-negative ints: ")

#     SysReadInt (nonneg)

#     SysPrintChar (' ')

#     SysExit ()

# end function main

#

# In the following pseucodecode, the while loop has been rewritten to use only an if

# statement and goto.

#

# function main ()

#     int a[128], i, neg, nonneg

#     SysSetSeed (1, 1234)

#     i = 0

#   main_loop_begin:

#     if i > 127 then goto main_loop_end

#     a[i] = SysRandInt (1, 1000) - 500 -- generates random integers in [-500, 500]

#     i = i + 1

#     goto main_loop_begin

#   main_loop_end:

#     neg, nonneg = count (a)

#     SysPrintStr ("Number of negative ints: ")

#     SysReadInt (neg)

#     SysPrintChar (' ')

#     SysPrintStr ("Number of non-negative ints: ")

#     SysReadInt (nonneg)

#     SysPrintChar (' ')

#     SysExit ()

# end function main

#

# This final revision now maps directly onto the assembly language implementation.

#

# STACK FRAME

# main() must allocate 131 words for local variables a, i, neg, and nonneg. Since

# main() does not return, we do not need to save $ra. The stack frame will look like

# this,

#

# +----------+

# |          | <-- $sp points here on entry to main()

# +----------+

# | nonneg | 520($sp)

# +----------+

# | neg     | 516($sp)

# +----------+

# | i       | 512($sp)

# +----------+

# | a[127] | 508($sp)

# +----------+

# | ...     |

# +----------+

# | a[2]    | 8($sp)

# +----------+

# | a[1]    | 4($sp)

# +----------+

# | a[0]    | <-- main() changes $sp to point here

# +----------+

#

#----------------------------------------------------------------------------------------

main:

    addi    $sp, $sp, -524                  # Allocate 131 words in stack frame

   

# SysSetSeed(1, 1234)

    addi    $v0, $zero, SYS_SET_SEED        # $v0 = SysSetSeed service code

    addi    $a0, $zero, 1                   # $a0 = pseudorandom number generator id

    addi    $a1, $zero, 1234                # $a1 = seed

    syscall                                 # SysSetSeed(1, 1234)

   

# for i = ...

    sw      $zero, 512($sp)                 # i = 0

    addi    $t9, $zero, 127                 # $t9 = index of last element of a

    addi    $t8, $zero, 500                 # $t8 = constant 500

   

main_loop_begin:

    lw      $t0, 512($sp)                   # $t0 = i

    bgt     $t0, $t9, main_loop_end         # if i > 127 drop out of loop

# a[i] = SysRandInt(1, 1000) - 500

    addi    $v0, $zero, SYS_RAND_INT_RNG    # $v0 = SysRandInt service code

    addi    $a0, $zero, 1                   # $a0 = pseudorandom number generator id

    addi    $a1, $zero, 1000                # $a1 = upper limit of range [0, 1000]

    syscall                                 # SysRandInt(1, 1000)

    sub     $t1, $a0, $t8                   # $a0 = SysRandInt(1, 1000) - 500

    sll     $t0, $t0, 2                     # $t0 = 4i

    add     $t0, $sp, $t0                   # $t0 = a + 4i = &a[i]

    sw      $t1, 0($t0)                     # a[i] = SysRandInt(1, 1000) - 500

   

# i = i + 1

    lw      $t0, 512($sp)                   # $t0 = i

    addi    $t0, $t0, 1                     # $t0 = i + 1

    sw      $t0, 512($sp)                   # i = i + 1

    j       main_loop_begin                 # continue looping

main_loop_end:

    move    $a0, $sp                        # $a0 = &a

    jal     count                           # Call count(a)

    sw      $v0, 516($sp)                   # neg = first return value

    sw      $v1, 520($sp)                   # nonneg = second return value

   

# SysPrintStr ("Number of negative ints: ")

    addi    $v0, $zero, SYS_PRINT_STR       # $v0 = SysPrintStr service code

    la      $a0, s_neg                      # $a0 = address of string to be printed

    syscall                                 # Call SysPrintStr(...)

   

# SysPrintInt (neg)

    addi    $v0, $zero, SYS_PRINT_INT       # $v0 = SysPrintInt service code

    lw      $a0, 516($sp)                   # $a0 = neg

    syscall                                 # SysPrintInt(neg)

   

# SysPrintChar(' ')

    addi    $v0, $zero, SYS_PRINT_CHAR      # $v0 = SysPrintChar service code

    addi    $a0, $zero, ' '                # $a0 = ' '

    syscall                                 # SysPrintChar(' ')

   

# SysPrintStr ("Number of non-negative ints: ")

    addi    $v0, $zero, SYS_PRINT_STR       # $v0 = SysPrintStr service code

    la      $a0, s_nonneg                   # $a0 = address of string to be printed

    syscall                                 # Call SysPrintStr(...)

   

# SysPrintInt (nonneg)

    addi    $v0, $zero, SYS_PRINT_INT       # $v0 = SysPrintInt service code

   lw      $a0, 520($sp)                   # $a0 = nonneg

    syscall                                 # SysPrintInt(nonneg)

   

# SysPrintChar(' ')

    addi    $v0, $zero, SYS_PRINT_CHAR      # $v0 = SysPrintChar service code

    addi    $a0, $zero, ' '               # $a0 = ' '

    syscall                                 # SysPrintChar(' ')

       

# Call SysExit()

    addi    $sp, $sp, 524                   # Deallocate stack frame

    addi    $v0, $zero, SYS_EXIT            # $v0 = SysExit service code

    syscall                                 # Call SysExit()

#----------------------------------------------------------------------------------------

# count() -

#----------------------------------------------------------------------------------------

count:

    jr      $ra

Download h3-Z.s from the course website. Read Appendix A which discusses how local array variables are allocated in the stack frame of a function and how an array is passed as an argument in a function call. Let array be a 1-dimensional array of ints. The size of array, i.e., the number of elements in array, is specified by variable n. Shown below is the pseudocode for a function count() which has array and n as parameters. This function walks through array counting the number of negative values and the number of non-negative values in the array. It returns both counts. function count (array: int[], n: int) rightarrow int, int int i, neg, nonneg for i leftarrow 0 to n - 1 do if array;

Explanation / Answer

main:

    addi    $sp, $sp, -524                  # Allocate 131 words in stack frame

   

# SysSetSeed(1, 1234)

    addi    $v0, $zero, SYS_SET_SEED        # $v0 = SysSetSeed service code

    addi    $a0, $zero, 1                   # $a0 = pseudorandom number generator id

    addi    $a1, $zero, 1234                # $a1 = seed

    syscall                                 # SysSetSeed(1, 1234)

   

# for i = ...

    sw      $zero, 512($sp)                 # i = 0

    addi    $t9, $zero, 127                 # $t9 = index of last element of a

    addi    $t8, $zero, 500                 # $t8 = constant 500

   

main_loop_begin:

    lw      $t0, 512($sp)                   # $t0 = i

    bgt     $t0, $t9, main_loop_end         # if i > 127 drop out of loop

# a[i] = SysRandInt(1, 1000) - 500

    addi    $v0, $zero, SYS_RAND_INT_RNG    # $v0 = SysRandInt service code

    addi    $a0, $zero, 1                   # $a0 = pseudorandom number generator id

    addi    $a1, $zero, 1000                # $a1 = upper limit of range [0, 1000]

    syscall                                 # SysRandInt(1, 1000)

    sub     $t1, $a0, $t8                   # $a0 = SysRandInt(1, 1000) - 500

    sll     $t0, $t0, 2                     # $t0 = 4i

    add     $t0, $sp, $t0                   # $t0 = a + 4i = &a[i]

    sw      $t1, 0($t0)                     # a[i] = SysRandInt(1, 1000) - 500

   

# i = i + 1

    lw      $t0, 512($sp)                   # $t0 = i

    addi    $t0, $t0, 1                     # $t0 = i + 1

    sw      $t0, 512($sp)                   # i = i + 1

    j       main_loop_begin                 # continue looping

main_loop_end:

    move    $a0, $sp                        # $a0 = &a

    jal     count                           # Call count(a)

    sw      $v0, 516($sp)                   # neg = first return value

    sw      $v1, 520($sp)                   # nonneg = second return value

   

# SysPrintStr ("Number of negative ints: ")

    addi    $v0, $zero, SYS_PRINT_STR       # $v0 = SysPrintStr service code

    la      $a0, s_neg                      # $a0 = address of string to be printed

    syscall                                 # Call SysPrintStr(...)

   

# SysPrintInt (neg)

    addi    $v0, $zero, SYS_PRINT_INT       # $v0 = SysPrintInt service code

    lw      $a0, 516($sp)                   # $a0 = neg

    syscall                                 # SysPrintInt(neg)

   

# SysPrintChar(' ')

    addi    $v0, $zero, SYS_PRINT_CHAR      # $v0 = SysPrintChar service code

    addi    $a0, $zero, ' '                # $a0 = ' '

    syscall                                 # SysPrintChar(' ')

   

# SysPrintStr ("Number of non-negative ints: ")

    addi    $v0, $zero, SYS_PRINT_STR       # $v0 = SysPrintStr service code

    la      $a0, s_nonneg                   # $a0 = address of string to be printed

    syscall                                 # Call SysPrintStr(...)

   

# SysPrintInt (nonneg)

    addi    $v0, $zero, SYS_PRINT_INT       # $v0 = SysPrintInt service code

   lw      $a0, 520($sp)                   # $a0 = nonneg

    syscall                                 # SysPrintInt(nonneg)

   

# SysPrintChar(' ')

    addi    $v0, $zero, SYS_PRINT_CHAR      # $v0 = SysPrintChar service code

    addi    $a0, $zero, ' '               # $a0 = ' '

    syscall                                 # SysPrintChar(' ')

       

# Call SysExit()

    addi    $sp, $sp, 524                   # Deallocate stack frame

    addi    $v0, $zero, SYS_EXIT            # $v0 = SysExit service code

    syscall                                 # Call SysExit()

#----------------------------------------------------------------------------------------

# count()

#----------------------------------------------------------------------------------------

count:

    jr      $ra