CS 330 - Lab 6
CS 330 - Lab 6
Introduction to MARS
Welcome to MIPS Assembly Language! We will introduce the MARS Simulator interface and
its basic navigation features, interact with the various registers in MIPS, write a simple "Hello
Assembly" program, print integers, characters, and floats, and perform basic arithmetic
operations.
Lab objectives
Page 1 of 17
o
Teach students how to declare data in the .data section using directives like .word,
.ascii, and .asciiz.
o Explain memory management concepts such as byte addressing and memory
alignment.
o Guide students on how to access and manipulate data stored in memory using
load and store instructions.
4. Debugging and Testing Techniques:
o Teach students how to debug MIPS assembly programs using the MARS
simulator's debugging features.
o Introduce techniques such as setting breakpoints, stepping through code,
inspecting register and memory contents, and tracking program flow.
o Encourage students to identify and troubleshoot common errors such as syntax
errors, logical errors, and runtime errors.
Materials:
To switch between the Edit and the Execute windows, use the tabs at the top.
The Execute window contains three main panes:
1. Text Segment: shows the machine code and related addresses.
2. Data Segment: shows memory locations that hold variables in the data segment.
3. Labels: shows addresses of labeled items, i.e. variables and jump endpoints.
There are two tabbed message areas at the bottom of Figure 1.1:
Page 2 of 17
1. The Mars Messages tab: Used for messages such as assembly or runtime errors and
informational messages. You can click on assembly error messages to select the
corresponding line of code in the editor.
2. The Run I/O tab: Used at runtime for displaying console output and entering console
input as program execution progresses.
Figure 1.2 shows the MARS Execute window’s panes, and emphasizes the following features:
1. The Execute window’s tab.
4. Controls for navigating the data memory area. Allows switching to view the stack
segment.
5. Switching between decimal and hexadecimal addresses and values in memory and
registers.
Page 3 of 17
7. Values stored in registers. These are directly editable.
8. Checkboxes used to setup breakpoints for each MIPS instruction. Useful in debugging.
At all times, the MIPS register window appears on the right-hand side of the screen,
even when you are editing and not running a program. While writing a program, this
serves as a useful reference for register names and their use. Move the mouse over the
register name to see the tool tips.
There are three register tabs:
The Register File: integer registers $0 through $31, HI, LO, and the Program Counter PC.
Coprocessor 0: exceptions, interrupts, and status codes.
Coprocessor 1: floating point registers.
Page 4 of 17
Figure 1.3: MARS screen after running the Assemble command.
After running the Assemble command, you can now execute the program. The Run menu and
the toolbar contain the following execution options:
Menu Item Icon Action
Run > Go Run the program to completion, or until the next breakpoint.
Run > Backstep Single-step backwards: “unexecute” the last executed instruction.
Page 5 of 17
The Run Speed Slider allows running the program at full speed or
slowing it down so you can watch the execution. Affects normal
execution only, not single-step execution.
You can set a breakpoint at any instruction by checking the checkbox in front of the instruction
in the text segment pane.
During execution, the instruction being executed is highlighted in yellow, and the register
that was last modified is highlighted in green. Also, the variable that was last updated in the
data segment is highlighted in blue. It’s usually only possible to see the highlighting when
you are stepping or running at less than full speed.
For more details about the MARS simulator, refer to the MARS documentation at the
following link: http://courses.missouristate.edu/KenVollmar/MARS/
Part 1 - Introduction:
• Every MIPS Program has two sections. These include the text and data
sections.
Part 2 - Registers:
Registers are the fastest memory in our computers. Registers are like variables. However,
unlike variables which store data in the main memory, registers store data in the processor itself
(exciting right!). Although Assembly language may seem complex, it gives you more control
and power over the registers as compared to high-level programming languages.
Registers Functions
$zero Constant for 0. Always 0
$at Reserved for assembler
$v0 - $v1 Expression evaluation and function results
$a0 - $a3 Stores arguments
Page 6 of 17
$t0 - $t9 Temporaries, not saved
$s0 - $s7 Contents saved for later use
$k0 - $k1 Reserved for OS kernel
$gp Global Pointer
$sp Stack Pointer
$fp Frame pointer
$ra Return Address
We must define the variables (in memory) to contain our string in the data section. Remember
that the computer understands only numbers, hence we need a system to represent strings with
numbers – ASCII.
In MIPS, strings are normally null-terminated as in C. Therefore, using .asciiz instead of ASCII
stores the specified string in the NULL-terminated format.
In the data section, declare a variable named firstMessage and store the null-terminated string
“Hello Assembly \n”.
What we are left with is to print the string right? We now need to perform a SYSCALL – the
interface between our program and the O.S kernel that allows us to perform services like print
strings, get user input or open files. Therefore, the syscall transfers control to the operating
system to perform a requested service.
Page 7 of 17
We need to tell the system what service to perform. Every syscall has a service number (See
https://courses.missouristate.edu/kenvollmar/mars/help/SyscallHelp.html for a list of
available syscall services).
Printing a string is service number 4. Our complete code for printing the string is:
Page 8 of 17
Part 6 – Printing a Float (Single-precision floating points: 32 bits)
Create a new file and name as print_float.asm. Again, the process is similar, however:
• The data type for a float is float.
• The syscall service number is 2.
• The value is loaded into argument register $f12 in the coprocessor1 using l.s – for
loading single-precision floating numbers. You can also use lwc1 – load word
coprocessor1. Remember, the coproc1 has the registers for single-precision floating
points.
Page 9 of 17
Part 8 – Printing string together with an integer, float, or double.
Congratulations! We can now print strings, characters, integers, floats and doubles! Let us print
a message that describes an integer, e.g., describing our mid-semester exam score.
Page 10 of 17
Let us try something interesting! Instead of declaring variables in memory, let us only use
registers for our program, which means that we will initialize our values to multiply directly
with registers and not load from memory.
NB: n-bit * n-bit = (n+n)-bit product size. For e.g, multiplying two 16-bit numbers results in a
32-bit product.
Using mul:
The mul operation allows us to multiply integers of 16-bit sizes. The product of 2 two 16-bit
integers will result in a 32-bit product size. Therefore, we can only use mul for operations
whose products are not more than 32 bits.
Using sll:
Shift Left Logical allows us to perform multiplication efficiently.
For instance, sll $t0, i = $t0 * 2 raise to the power i.
Page 11 of 17
Like multiplication, there are several ways of performing the division operation. The simplest
and most common is similar to the add, sub, and mul operations.
Using div:
You can also use the div operation in various forms when you hover your cursor on the div
keyword. Let us see an interesting one here – we want to be able to display the quotient and
remainder, if any. Here, div takes only two registers (the numbers involved in the division
operation). The quotient is stored in the lo register, while the remainder is stored in the hi
register.
Using srl:
Shift Right Logical allows us to perform division efficiently.
For instance, srl $t0, i = $t0 / 2 raised to the power i.
Page 12 of 17
NB: Unfortunately, MIPS does not support immediate floating-point arithmetic instructions,
so we must load values into a floating-point register first.
Page 13 of 17
Part 12: Getting inputs from the user.
The syscall service number for reading an integer is 5, a float is 6, a double is 7 and a string is
8.
Let us create a simple program to ask the user to input their age (integer) and display a message
showing their age on the screen. Name as readInt.asm
Let us look at how to use the conditional if statement in MIPS to compare two values.
Page 14 of 17
How can we write the same program using bne?
Page 15 of 17
Part 15: Post-Lab Deliverable
Task 1: Write an assembly program that prompts the user to enter three integers, and then
checks if the first integer is equal to the sum of the second and third integers. If it is, print "The
first number is equal to the sum of the second and third numbers"; otherwise, print "The first
number is not equal to the sum of the second and third numbers".
Task 2: Write an assembly program that prompts the user to enter four integers, and then
checks if the difference of the first two is equal to the difference of the last two. If it is, print
"The differences are equal"; otherwise, print "The differences are not equal".
Page 16 of 17
3. What are some common pitfalls and challenges encountered when programming in the
MIPS assembly language?
4. How does the MARS simulator aid in learning and debugging MIPS assembly language
programs?
Submission:
Submit a zip file that contains:
• Task 1 and 2 codes in Part 15
• PDF of written responses to the reflection questions.
Name the zip file ID_Lab6.
Page 17 of 17