Author: This lab is derived by Zack Kurmas from a lab designed by Greg Wolffe. Some modifications by Andrew Kalafut
Objective: The purpose of this lab is to closely examine an example instruction set --- specifically, the instruction set for the MIPS R2000 RISC chip.
Deliverables: Submit in hardcopy your answers to the numbered questions.
This project should preferably be done in groups of 2. If there are sufficient lab computers available, you may work alone. However, if you have not used the MARS software in CIS 251, I encourage you to find a partner who did.
We will be using a graphical MIPS simulator called
MARS. In this lab, you will use MARS to examine the contents of
memory and CPU registers and to show the machine instructions
generated for each assembly language statement.
spimand describes both
spimand the MIPS instruction set. Much of the information is relevant to MARS also. It is over 80 pages long, so do not print it all out in the EOS or arch labs.
MARS in installed locally. Just type
mars from the command line. You can also download
the jar file and run your own copy on your personal machine.
The current version of MARS is 4.2. Check that you are using the current version.
Older versions generate slightly different machine code.
Download the assembly program file named
exampleCIT-1.s (either cut and paste it or
use a right-click). Then, open it in MARS (File --> Open, or click the
"Open a file for editing" button). This file is the minimal MIPS program.
There is an empty data portion; the code portion consists of
main function that simply calls the
call. Comments are given by the text on a line following
Registers display on the right. In this particular MIPS processor,
all registers hold 32-bits of data. Their current contents are printed in
hexadecimal. (Registers will be described in more detail in the
Assemble button (the one with a screwdriver and wrench). In
the "Execute" window, you will see the contents of both the text (code)
and data segments of memory.
Mars simulates a MIPS
processor with a single, 4GB, byte-addressable memory. This is in
contrast to the processor we are building in class which has separate
memories for instructions and data.
The Text Segment window displays the instructions. Each line contains 5 columns:
Let's take a closer look at the
registers in this processor. The
PC register is,
of course, the Program Counter. Upon loading a program, the PC
will be initialized to the beginning of the text segment. (In other
words, the program counter holds the address of the first instruction
to be executed.) Registers are
designated either by their number (
R0..R31) or by
their name (e.g.
R0 is hard-wired to always hold the value 0. Register
use by the assembler (it is often used as an address register) and
(k) registers are for the use of the operating
system (kernel). Registers
(v1) are used for system call argument passing and
(a0)..(a3) are used to pass arguments to
(t) registers are for temporary
storage and the
(s) registers are used for
semi-permanent storage (across function calls). Finally, there
is the stack pointer
(sp), the global
(gp), and the return address
Download, load, and assemble
exampleCIT-2.s. This program simply
declares a variable named
val and stores the value 42 in
.word directive declares
to be an entire memory word in size. Knowing its value, you should
now be able to find where
val is stored in memory (it
will be located somewhere in the data segment). Recall that all
values are in hexadecimal.
Note: At this point, you may find the built in KDE calculator (with hex conversion) useful.
Mars. By this, I mean, draw a column labeled
0x00000000at the bottom and
0xffffffffat the top. Then, show which portions of this address space are used used for instructions, user data, the stack, kernel data, etc. Hint: You will have to look in different MARS windows to find these different parts. Also, The stack grows "down", meaning that each data item added to the stack has a smaller address than the previous item.
Load and compile
run button will cause execution of your
program. However, you will usually want to step through you
program one instruction at a time - to do this use the
button (an arrow with a "1" on it). Watch the value of the Program
Counter as you step through the code.
Closely examine the instructions corresponding to source code lines
10 through 13.
Normally, each assembly language instruction corresponds to one
machine-language instruction. In this case, the second
addi and the two
instructions are broken into multiple machine-language instructions. In the case of the
lw, the first
lui) loads a value into register
(at) register - recall its use). The
second instruction actually performs the desired data transfer.
addipseudo-instruction on line 11 produce?
lui" stand for? (Hint: Look on page A-57 in the SPIM guide.)
addiinstructions result in different numbers of actual instructions? (Hint: Write each constant out in hex.)
luiinstruction generated for line 12? Why is this the immediate value that is used (i.e., what does it represent)? Hint: Look in the Data Segment window.
lwinstruction). Notice that this instruction has three parameters. Describe the function of all three parameters. (Hint: Examine the machine language generated for lines 13 and 15 as well as the description of
lwon page A-67.)
lwto be able to access the entire 4GB memory space; or, could you eliminate the offset parameter? (In other words: If
lwdid not have an offset parameter, would there be memory locations that could not be read using
lw?) If so, give an example. If not, give a sequence of machine instructions that could be used to load
$t1with a 2-parameter version of
lwis useful. Include an explanation of how can it be used to "make the common case fast." (In other words, how it can be used to reduce the number of instructions needed by the program.) (Hint: Look for redundant code in the execute window for
lw. In particular, include an explanation of how the third parameter can potentially slow the computer. (Think in terms of the hardware configuration needed for this instruction.)
add_xy.s, which requests two
integers from the user and prints their sum. Run and review this code
until you remember / learn how it works. The system calls for
performing I/O are discussed on page A-43 of the SPIM guide.
lipseudo-instruction implemented? In other words, which "real" instructions are used to implement the
lipseudo-instruction? (Remember, register 0 always contains the value 0.)
movebe faster than the MIPS implementation? Why or why not? Consider the effects on both the time for the individual instruction, and the overall speed of the processor.
add_xy.smarked with a "*" in the comment (17, 18, 29, 30, 41, 42, and 72) complete a table showing how the assembly-language instruction is mapped into a machine-language instruction. For pseudo-instructions, create one table for each machine instruction produced by the assembler. You may use this template for your tables. Use the example below as a model:
|Assembly instruction||add $s2, $s0, $s1|
|Machine instruction (hex)||0x02119020|
|Machine instruction (binary)||000000||10000||10001||10010||00000||100000|
|Instruction field (decimal)||0||16||17||18||0||32|
beqinstruction on line 30? Where does this number come from (i.e., how does the assembler calculate it)?
jinstruction on line 72? (Be careful, you need to look at the actual hex value of the instruction, not the number in the "Basic" column.) Where does this number come from (i.e., how does the assembler calculate it)?