You are here: Home / ECPE 170 / Labs / Lab 10: MIPS Assembly Programming (Basic)

Lab 10: MIPS Assembly Programming (Basic)

Overview

In this lab, you will gain experience with the SPIM simulator and MIPS assembly programming by writing a sequence of programs with increasing complexity.

 

Lab - Getting Started

We will be using SPIM, a MIPS simulator, in order to learn assembly programming.  Before lab, you should complete the QtSPIM tutorial, including installing the simulator and running your first program.

Familiarize yourself with the various MIPS reference materials on the Resources page, particularly the MIPS Instruction Set overview.

Review the MIPS Example Programs to see basic arithmetic, looping, I/O, and function calls, plus good assembly programming style.

If you are using the GEdit text editor, don't forget to install the syntax highlighting extension, which makes your code easier to read.

 

Programming Requirements (for all exercises):
(1) File names: Names your assembly source code something which makes it obvious what the file contains, like: part1.asm
(2) Commenting: **Each line** of assembly code must be documented with a comment!
This comment can be terse. For example,  "i++" is a  perfectly reasonable comment for the line addi $t1,$t1,1 where register $t1 holds the loop counter i.
(3) Commenting: Each region of assembly code must clearly have a **comment block** documenting the overall purpose of that region, along with what values each register holds. You can use your own judgement for a reasonable region size.

 

Lab Submission:
(1) All source code and lab report PDF must be submitted via Mercurial. Place the source files inside the lab10 folder that was previously created.

 

Lab Part 1 - Arithmetic

Write a complete MIPS program that calculates the equation shown below (in C):

int main()
{
   int A=15;
   int B=10;
   int C=7;
   int D=2;
   int E=18;
   int F=-3;
   int Z=0;

   Z = (A+B) + (C-D) + (E+F) - (A-C);
}

A-F can be stored in temporary registers.  However, the final result Z must be an integer word stored in memory when your program finishes executing.  It is also a good idea to write this C/C++ program and run it to be sure your assembly code uses the same operator precedence rules.

Lab Report:
(1) Take two screenshots of the MIPS register panel: one before your program runs, and one after your program finishes.  Put the register panel in Decimal mode (right-click) so it is easy to see register values.
(2) Take two screenshots of the MIPS memory panel (data tab): one before your program runs, and one after your program finishes.   Put the memory panel in Decimal mode (right-click), so it is easy to see memory values.  In the after-execution capture, circle the memory location (not register) that contains the final calculated value of Z.

 

Lab Part 2 - Branches

Write a complete MIPS program that implements the same algorithm shown below (in C):

int main()
{
   // Note: I should be able to change
   // the values of A, B, and C when testing
   // your code, and get correct output each time!
   // (i.e. don't just hardwire your output)
   int A=10;
   int B=15;
   int C=6;
   int Z=0;


   if(A > B || C < 5)
      Z = 1;
   else if( !((A > B) && ((C+1) == 7)))
      Z = 2;
   else
      Z = 3;

   switch(Z)
    {
      case 1:
         Z = -1;
      case 2:
         Z -=-2;
      case 3:
         Z -= -3;
         break;
      default:
         Z = 0;
        break;
    }
}

A-C and Z must be integer words in memory, both when the program begins and when the program ends.  In between, they can be stored in registers.

Tip: Consult the Resources page for extra MIPS instructions (or pseduo-instructions) to make the task of comparing values and branching easier.

 

Lab Report:
(3) Take two screenshots of the MIPS register panel: one before your program runs, and one after your program finishes.  Put the register panel in Decimal mode (right-click) so it is easy to see register values.
(4) Take two screenshots of the MIPS memory panel (data tab): one before your program runs, and one after your program finishes.   Put the memory panel in Decimal mode (right-click), so it is easy to see memory values.  In the after-execution capture, circle the memory location (not register) that contains the final calculated value of Z.

 

Lab Part 3 - Loops

Write a complete MIPS program that implements the algorithm shown below (in C):

int main()
{
   int Z=2;
   int i;

i=0;
while(1){
if(i>20)
break;
Z++;
i+=2;
}
do {
Z++;
} while (Z<100);

while(i > 0) {
Z--;
i--; }

I and Z must be integer words in memory.

Lab Report:
(5) Take a screenshot of the MIPS register panel after your program finishes.  Put the register panel in Decimal mode (right-click) so it is easy to see register values.
(6) Take a screenshot of the MIPS memory panel (data tab) after your program finishes.   Put the memory panel in Decimal mode (right-click), so it is easy to see memory values. Circle the memory location (not register) that contains the final calculated values of I and Z.

 

Lab Part 4 - Arrays

Write a complete MIPS program that implements the same algorithm shown below (in C):

int main()
{
   int A[5]; // Empty memory region for 5 elements
   int B[5] = {1,2,3,4,5};
   int C=12;
   int i;

   for(i=0; i<5; i++)
{
A[i] = B[i] + C;
}

i--;
while(i >= 0)
{
A[i]=A[i]*2;
i--;
} }

A and B must be arrays of integer words in memory, but i can be a register.

Lab Report:
(7) Take a screenshot of the MIPS register panel after your program finishes.  Put the register panel in Decimal mode (right-click) so it is easy to see register values.
(8) Take a screenshot of the MIPS memory panel (data tab) after your program finishes.   Put the memory panel in Decimal mode (right-click), so it is easy to see memory values.  Circle the final values of array A.

 

Lab Part 5 - I/O, Loops, and Arrays

Write a complete MIPS program that implements the same algorithm shown below (in C):

int main()
{
  char string[256];
  int i=0;
  char *result = NULL;  // NULL pointer is binary zero
  
  // Obtain string from user, e.g. "Constantinople"
  scanf("%255s", string); 
  
  // Search string for letter 'e'.
  // Result is pointer to first e (if it exists)
  // or NULL pointer if it does not exist
  while(string[i] != '\0') {
    if(string[i] == 'e') {
      result = &string[i]; 
      break; // exit from while loop early
    }
    i++;
  }

  if(result != NULL) {
    printf("First match at address %d\n", result);
    printf("The matching character is %c\n", *result);
  }
  else
    printf("No match found\n");
}

The array of characters is an array of bytes, not words! The result pointer must be stored in memory when the program finishes.

Lab Report:
(9) Take a screenshot of the MIPS memory panel (data tab) after your program finishes.   Put the memory panel in Hex mode (right-click), since Decimal mode will not allow us to distinguish between bytes.  Circle two things: the final value of the pointer 'result' in memory, and the corresponding location that result points to. Does that location in memory contain the ASCII code for the character 'e'? (If not, you had better check your work!)

Extra Credit (10 points): 
Extend your assembly program to also print out the address of the matching character (i.e. the result variable) as a hexadecimal number in addition to a decimal number.
This should be the equivalent of printf("%X", result);

 

(Optional) Lab Report:
(1) How would you suggest improving this lab in future semesters?