COMP 411, Lab 6: Basic MIPS Assembly Programming

Due Sunday, February 25, 2018, 11:59 PM

Exercise 0

For this exercise, you will download the MARS assembler, and run a few simple MIPS assembly programs from the course website.

First, download MARS (link on course website, under Reference Materials). Launch it by double-clicking the .jar file. Familiarize yourself with the menu.

Configure it as follows: Settings->Permit extended (pseudo) instructions and formats is enabled, and Settings->Memory Configuration->Compact, Data at Address 0 is selected. The first setting allows us to use pseudo-instructions when convenient, and the second setting tells the assembler where it can expect to place data and code in memory.

Download three assembly files from the course website: Sum.asm, SumArray.asm and Fibonacci.asm.

Use the File->Open menu to open one of these programs. Assemble (i.e., compile) the program by hitting Run->Assemble, or by hitting the screwdriver/wrench icon, or by pressing F3. Run the program by hitting Run->Go, or by hitting the icon with the play button. You may single-step through the program by hitting Run->Step, or hitting the icon with the '1' to the right of the play button. You can also set one or more breakpoints by checking the box to the left of the instructions where you want execution to break, and then hit Run.

The bottom pane has two tabs: Mars Messages shows errors or warnings during assembly; Run I/O is the input/output.

Run each of the three programs. Make sure you understand every single line of code. Here is what to expect for each:

MARS syscall

There are several library routines provided by MARS that an assembly program can use. These are called system calls, or syscall. These services include support for printing integers and strings (similar to the printf() function in C), reading integers and strings from the keyboard (similar to scanf() in C), memory allocation (similar to malloc() in C), exiting from a program (similar to return from main() in C), etc.

An assembly program accesses those services using the syscall command. There is only one syscall command for all these services, but which service is requested is determined by the values provided in certain registers. The value in register $v0 determines which service is requested, and often parameters are passed to the service using registers $a0, $a1, $a2 and $a3. If a value needs to be returned to the program (e.g., reading an integer from keyboard), it is typically returned in register $v0.

For a full listing of system calls available in MARS, please refer to http://courses.missouristate.edu/kenvollmar/mars/help/syscallhelp.html. We will mostly be using system calls numbered 1 to 17.

For example, to exit a program, you would use syscall with 10 in $v0:

	addi $v0, $0, 10			# system call 10 for exit
	syscall					# exit the program

The li pseudoinstruction

Sometimes the instruction addi $v0, $0, 10 is shortened to the more readable pseudo-instruction li $v0, 10, which stands for ("load the immediate value 10 into $v0").

The la pseudoinstruction

As another example, suppose you want to print a string labeled myString. Remember that myString is simply a location in memory starting where the contents of the string are stored. You would use syscall with 4 in $v0 for printing strings. This system call expects the register $a0 to contain the address of the starting memory location where the string is stored. An easy way to put that address in register $a0 is to use the la pseudo-instruction. It stands for "load the address of". Here is a code fragment that prints the string labeled myString:

	li $v0, 4				# system call 4 for printing a string
	la $a0, myString 			# put the address of string in $a0
	syscall					# print the string

Study all of the system calls from 1 to 17.


Exercise 1

You are given a program in MIPS assembly language that computes the area of a rectangle given the width and the height (ex1.asm). The width and height are read from the standard input after prompting the user, and then the program computes the area and prints it on the standard output. Here's an example scenario:

Enter width (integer):
2
Enter height (integer):
4
Rectangle's area is 8

Modify the program so that it also calculates and prints the perimeter (i.e., sum of all sides) of the rectangle. Thus, after modification, the example scenario would become:

Enter width (integer):
2
Enter height (integer):
4
Rectangle's area is 8
Its perimeter is 12

Test your program in MARS on a few different inputs to verify that it is working correctly. You can simply enter the inputs within the MARS "Run I/O" window. Once you are satisfied that the program is working fine within MARS, follow the directions below to copy it to classroom.cs.unc.edu, and then run the self-checking script. Make sure that the program passes the self-checker. If you see errors, you can open the program in pico and edit on the server, or you can edit on the laptop and then copy again to classroom. When you are done with all the exercises, use the submit script to submit your work.


Exercise 2

Copy the file ex1.asm to ex2.asm. Modify the program in ex2.asm to make it work on multiple inputs. In particular, it should repeatedly ask for width and height values, and print the corresponding area and perimeter, until the user enters the value 0 for width. At that point, the program should terminate. Here's an execution scenario:

Enter width (integer):
2
Enter height (integer):
4
Rectangle's area is 8
Its perimeter is 12
Enter width (integer):
5
Enter height (integer):
6
Rectangle's area is 30
Its perimeter is 22
Enter width (integer):
0

Essentially, this exercise involves introducing a loop around the main code of Exercise 1. As long as width is not equal to 0, the program repeats by looping back to the top of the loop. If width is 0, the program breaks out of the loop. The key instructions for forming such loops are: beq, bne and j. You may need one or more of these, depending on how you construct your loop.

Test your program in MARS, and once you are satisfied that it is working properly, follow the directions below to copy it to classroom.cs.unc.edu, and then run the self-checking and submit scripts.


Exercise 3

For this exercise, you are to write an assembly program to convert red-green-blue (RGB) values for a set of pixels into a single gray value per pixel. First, study the C version of the program (ex3.c), and compile and run it. Your task is to convert this C program into an equivalent MIPS assembly program.

For writing the MIPS assembly version, use the starter file ex3.asm. Your code must strictly follow these specifications:

You are given an array called pixels, each element of which is a 32-bit word representing a color value. The lowest significant 8 bits of each color value denote an unsigned integer (from 0 to 255) representing the color's "blue" value, the next 8 bits are the "green" value, the next 8 bits are the "red" value, and the most significant 8 bits are all zeroes. For example, the pixel with value 0x0001ff22 has color components: red = 1 (or 0x01), green = 255 (or 0xff), blue = 34 or (0x22).

For this programming assignment, you will read through this array of pixels, and for each pixel, convert the color pixel into a grayscale pixel using a simple formula: gray value = (red + green + blue) / 3. Note the division is integer divide and truncate (i.e., no rounding needed). For the above example, the gray value would be (1+255+34) / 3 or 96.

The calculation of the gray value should be done in a separate procedure called rgb_to_gray. (Note: For this simple task, there is no need to create and use a stack. This is because there are no nested procedure calls, and the calculation is fairly trivial, so no sophisticated management of register saves/restores is needed.) We simply use the jal instruction to call a procedure, and the jr instruction to return from that procedure.

After calculating the gray value for a pixel, print it out to the console (only one element per line). The program keeps reading RGB values and printing the corresponding gray value, until it encounters an input of -1. The expected output format is given in the comments in the starter file on the course website.

Hint: Study and understand the divide instruction thoroughly before attempting to use it!

Name the file containing your code ex3.asm. Assemble and run your program in MARS, and make sure it produces the correct output (see near the top of the starter file). You do not need to enter any inputs; all the data is embedded within the program as the array called pixels.


Test Inputs, Due Date and Submission Procedure

Your assignment must be submitted electronically by 11:59pm on Sunday, February 25.

Sample input and output files are provided for Exercises 1 and 2 on the classroom server at /home/porter/comp411/samples/lab6. There is no input file needed for Exercise 3; the input data is embedded within the assembly file. The expected output for Exercise 3 is available under the sample folder, but it is also specified as a comment at the top of the provided assembly file.

Once you are satisfied that your assembly programs are running fine within MARS on your laptop, copy the files ex1.asm, ex2.asm and ex3.asm to the server (classroom) under the appropriate folder in your home directory (e.g., comp411lab/lab6). Here is a reminder on how to transfer files between your personal computer and the server:

Then, log in to classroom, and run the self-checking and submit scripts as you normally do:

 % cd ~/comp411lab/lab6
 % /home/porter/comp411/bin/selfchecklab6
 % /home/porter/comp411/bin/submitlab6

In case of any problems, please contact the instructor or the TAs.


18 October 2017, Montek Singh, montek@cs.unc.edu
Modified 15 February 2018, Montek Singh, montek@cs.unc.edu

Last updated: 2018-02-17 12:08:17 -0500 [validate xhtml]