# PCSPIM: MIPS Control Instructions and working with Arrays

In this article, we will understand MIPS control instructions by examples. MIPS control instructions are a fundamental aspect of programming in MIPS assembly language. They allow you to control the flow of your program, make decisions, and loop through code based on conditions.

## MIPS Control Instructions

Here are some common MIPS control instructions:

### Conditional Branching Instructions

• beq (Branch on Equal): Branches if two registers are equal.
• bne (Branch on Not Equal): Branches if two registers are not equal.
• bgtz (Branch on Greater Than Zero): Branches if a register is greater than zero.
• blez (Branch on Less Than or Equal to Zero): Branches if a register is less than or equal to zero.
• bgez (Branch on Greater Than or Equal to Zero): Branches if a register is greater than or equal to zero.
• bltz (Branch on Less Than Zero): Branches if a register is less than zero.

### Unconditional Jump Instructions

j (Jump): Jumps to a specified address.
jal (Jump and Link): Jumps to a specified address and saves the return address in \$ra (return address register).

### Comparison Instructions

• slt (Set Less Than): Sets a register to 1 if one register is less than another; otherwise, sets it to 0.

### Function Calls

• jr (Jump Register): Jumps to an address stored in a register (typically used for returning from functions).
• jal (Jump and Link): Jumps to a function and stores the return address in \$ra.

Working with arrays in MIPS involves using these control instructions along with load and store instructions to access and manipulate array elements. Here’s a high-level overview of working with arrays in MIPS:

## MIPS Control Instructions Examples

In this example, we will use both branch and jump instructions to sum the first ten positive integers (10+9+8+7+…). Follow along with the code provided below and fill in the missing parts:

``````.text
.globl main

main:
addi \$s0, \$zero, 10           # counter initialized to 10
addi \$t0, \$zero, 0            # sum/accumulator initialized to 0

loop1:
add \$t0, \$t0, \$s0             # Performing accumulation in \$t0
addi \$s0, \$s0, -1             # counter−−
bne \$s0, \$zero, loop1         # Exit the loop after 10th iteration
nop                           # Few no operations to indicate end of interest
nop
``````

After running the program, the value of `\$t0` will be `0x00000037` in hexadecimal or `55` in decimal when we reach the end of the program (after the first `nop`).

### Exercise 2

Now let’s modify the program from Exercise 1 to calculate the sum of powers of 2 (1+2+4+8+16+32+…) for the first 20 numbers. Use the registers mentioned in Exercise 1, i.e., `\$s0`, `\$t0`, and `\$zero`. You can also use `\$t1`. Two possible implementations are shown below:

#### Implementation 1:

``````.text
.globl main

main:
addi \$s0, \$zero, 20           # counter initialized to 20
addi \$t0, \$zero, 0            # sum/accumulator initialized to 0
addi \$t1, \$zero, 1            # \$t1 initialized with “1”

loop1:
add \$t0, \$t0, \$t1             # Performing accumulation in \$t0
add \$t1, \$t1, \$t1             # Calculating new number to be added
addi \$s0, \$s0, -1             # counter−−
bne \$s0, \$zero, loop1         # Exit the loop after 20th iteration
nop
``````

After running this program, the final sum will be `0x000fffff` in hexadecimal or `1048575` in decimal.

#### Implementation 2:

``````.text
.globl main

main:
addi \$s0, \$zero, 20           # counter initialized to 20
addi \$t0, \$zero, 0            # sum/accumulator initialized to 0
addi \$t1, \$zero, 1            # \$t1 initialized with “1”

loop1:
add \$t0, \$t0, \$t1             # Performing accumulation in \$t0
sll \$t1, \$t1, 1               # Calculating new number to be added
addi \$s0, \$s0, -1             # counter−−
bne \$s0, \$zero, loop1         # Exit the loop after 20th iteration
nop
nop
``````

After running this modified program, the final sum will still be `0x000fffff` in hexadecimal or `1048575` in decimal.

### Solution for Implementation 1:

Let’s modify the program from Implementation 1 to calculate the sum of more numbers. We will increase the number of loops to 50 and observe the intermediate sum contained in `\$t0` when an overflow occurs in any of the registers involved:

After running the modified program for 50 numbers, when an overflow occurs, the intermediate sum contained in `\$t0` will be `0x7fffffff` in hexadecimal. We can identify the overflow by the exception caused due to an arithmetic overflow. However, note that the overflow was not caused by the intermediate sum but by the new number obtained using the instruction `(add \$t1, \$t1, \$t1)`. This instruction performs a signed addition. When the value in `\$t1` reaches `0x40000000`, an overflow occurs and the program jumps to the kernel part of the code due to the exception caused by an arithmetic overflow into the signed bit.

Now, let’s repeat the above program for 50 numbers but this time use the `addu` instruction instead of `add` while calculating the sum. We will observe the first value of the intermediate sum for which an overflow occurs:

After running the modified program with the `addu` instruction, the first value of the intermediate sum for which an overflow occurs is `0xffffffff` in hexadecimal. This overflow is caused by the new number obtained by the instruction `(addu \$t1, \$t1, \$t1)`. The overflow is caused because the value of `\$t1` becomes `0x100000000`, which cannot be accommodated in the 32-bit space. At this point, the value in `\$t1` becomes zero, and the register `\$t0` contains `0xffffffff` for the rest of the program. It is important to note that this overflow occurs at a different point compared to the signed addition case, because the unsigned addition does not cause an exception but overflows in `\$t1` due to running out of space.

### Solution for Implementation 2:

Similarly, let’s modify Implementation 2 to calculate the sum of more numbers (50 numbers) and observe the intermediate sum contained in `\$t0` when an overflow occurs:

After running the modified program for 50 numbers, when an overflow occurs, the intermediate sum contained in `\$t0` will be `0xffffffff` in hexadecimal. We can identify the overflow by observing that the instruction `add \$t0, \$t0, \$t1` performs the signed accumulation, while the instruction `sll \$t1, \$t1, 1` creates the new number to be added on each iteration. When the value in `\$t1` reaches `0x40000000`, an overflow occurs and the value of `\$t0` becomes `0xffffffff`.

On the next left shift operation, the number `0x80000000` becomes `0x100000000`, which cannot be accommodated in a 32-bit space. As a result, `\$t1` becomes `0x00000000`. This can be classified as a logical overflow beyond the available 32-bit space. The contents of `\$t0` at this point are `0xffffffff`, and this value remains in `\$t0` until the end of the program.

To observe the same behavior with the `addu` instruction, repeat the above program (of the same 50 numbers) using the `addu` instruction instead of `add`. The value and overflow occur at the same point in this case.

## Using Array in MIPS Assembly Language

Let’s see example to use arrays in MIPS assembly language with or without control and branch instructions.

### Summing the Integers in an Array

Now, let’s write a program without using branches to sum the integers in an array with 5 elements. We will save the result in the variable “sum”. The starting code is provided below:

``````.data
myData:   .word  2, 12, -5, 7, 4    # array initialization
sum:      .word  0    # this will contain the sum

.text
.globl   main
main:
la   \$s0, myData      # load the address of myData into \$s0
li   \$t2, 0           # initialize \$t2 to save the sum

lw \$t0, 0(\$s0)
add \$t2, \$t2, \$t0

lw \$t0, 4(\$s0)
add \$t2, \$t2, \$t0

lw \$t0, 8(\$s0)
add \$t2, \$t2, \$t0

lw \$t0, 12(\$s0)
add \$t2, \$t2, \$t0

lw \$t0, 16(\$s0)
add \$t2, \$t2, \$t0

la   \$s0, sum      # Load the address of "sum" into \$s0
sw   \$t2, 0(\$s0)   # Store the value of the final sum from \$t2 to the memory location at "sum"
``````

After running this program, the value of `sum` will be `0x00000014` in hexadecimal or `20` in decimal.

Below are the missing values filled in the table:

### Summing the Integers in an Array using Branch Instructions

Let’s repeat Exercise 3 but this time use branch instructions and the following 15-element array:

``````.data
myData:   .word  200, -1299, -5000, 7123, 4, -2, 3, -7, 89, 4, -1000, 11, 0, 14, -1
sum:      .word  0    # this location will contain the sum

.text
.globl main
main:
la   \$s0, myData        # load the address of myData into \$s0
li   \$t1, 15            # initialize the index
add  \$t2, \$zero, \$zero  # initialize to save the sum in \$t2

loop:
addi \$t1, \$t1, -1
sll  \$t3, \$t1, 2        # Multiply the index by 4 to get the offset
add  \$t3, \$s0, \$t3      # Calculate the memory address of the current element
lw   \$t0, 0(\$t3)        # Load the value from memory
add  \$t2, \$t2, \$t0      # Add the value to the sum in \$t2
bne  \$t1, \$zero, loop   # Continue until the index becomes zero

exit:
la   \$s0, sum           # Load the address of "sum" into \$s0
sw   \$t2, 0(\$s0)        # Store the value of the final sum from \$t2 to memory
``````

After running this program, the value of `sum` will be `0x0000008b` in hexadecimal or `139` in decimal. The branch instruction produced by the assembler is `bne \$9, \$0, −20`.

#### How Does this Code Work?

This MIPS assembly code calculates the sum of the elements stored in an array named `myData` and stores the result in a memory location named `sum`. Here’s a step-by-step explanation of what the code does:

1. In the `.data` section, an array `myData` is defined with 15 integer values. Another memory location `sum` is also reserved to store the sum of the array elements.
2. In the `.text` section, the program starts with the `main` function:
• The base address of the `myData` array is loaded into register `\$s0` using the `la` (load address) instruction.
• Register `\$t1` is initialized to 15, representing the index of the last element in the array.
• Register `\$t2` is initialized to zero to store the sum of the elements.
3. The program enters a loop labeled as `loop`:
• It decrements the index in `\$t1` by 1.
• It calculates the memory address of the current element using the index by multiplying it by 4 (since each element is 4 bytes) and adding it to the base address in `\$s0`. The result is stored in `\$t3`.
• It loads the value from memory at the calculated address into `\$t0`.
• It adds the loaded value (`\$t0`) to the running sum (`\$t2`).
4. The loop continues to the next element until the index (`\$t1`) becomes zero. At this point, the sum of all elements in the array is stored in `\$t2`.
5. The program exits the loop and proceeds to the `exit` section:
• The address of the `sum` memory location is loaded into `\$s0`.
• The final sum stored in `\$t2` is stored in the memory location pointed to by `\$s0`, which is `sum`.

In summary, this code calculates the sum of the elements in the `myData` array and stores the result in the `sum` memory location. It demonstrates the use of load and store instructions, indexing, and looping in MIPS assembly to perform a common array operation.

## Conclusion

In conclusion, this article provided an in-depth understanding of MIPS control instructions through examples. We explored conditional branching instructions, unconditional jump instructions, and comparison instructions. We also learned about function calls and how to work with arrays in MIPS assembly language. By going through the provided exercises and modified implementations, we were able to gain hands-on experience with these control instructions and observe their effects on program execution. Overall, this article serves as a comprehensive guide for anyone looking to enhance their proficiency in programming with MIPS control instructions.

Related content: