Vous êtes sur la page 1sur 8

LAB 1

1. Objective

This laboratory assignment will help you familiarize yourself with SPIM, the MIPS simulator
developed by James R. Larus. You are to code and run your simple MIPS assembly language
programs.

2. Introduction to SPIM

SPIM is a software simulator that loads and executes assembly language programs for the
MIPS32 RISC architecture. It is a self-contained system for running these programs and contains
a debugger and interface to the operating system. The current version of SPIM is 7.2.

SPIM was written by James R. Larus, then at the Computer Sciences Department of University
of Wisconsin, Madison (larus@cs.wisc.edu). SPIM is very portable, which allows students to
generate code for a simple, clean, orthogonal computer. SPIM currently runs on a wide variety of
Unix, DOS and Windows systems. SPIM is copyrighted by James Larus and can be freely used
for non-commercial purposes. You can get source and pre-compiled files from
http://www.cs.wisc.edu/~larus/spim.html.

You will find the Windows version of spim, PCSpim, installed on the department Windows PCs
in your lab. Locate it under the Start Menu and ensure that it starts up.
You will also find the UNIX version of spim installed on the department server.

For this lab you will run your Assembly programs with PCSpim.

3. Your first MIPS Assembly program [50 points]


## Your first MIPS assembly program
## Notice the stylized format of the code: 3 columns:
## (1) Optional labels,
## (2) Machine instructions, assembler directives and their operands,
## (3) Optional comments: everything to the right of a '#' until end of line
is
## ignored.

.data # "data section" global, static modifiable data

SID: .word 100


spc1: .asciiz " "
nl: .asciiz "\n"
tb: .asciiz "\t"
msg1: .asciiz "Hello, World\n"
msg2: .asciiz "My name is: XXXXXXXXX\n"
msg3: .asciiz "\nMy name is still XXXXXXXXX !\n"
.text # "text section" code and read-only data

.globl main # declare `main' as a global symbol

main: la $a0, msg1

li $v0, 4 # "print string" system call


syscall

la $a0, msg2
li $v0, 4
syscall

lw $a0, SID
la $a1, spc1

Loop: beq $0, $a0, Exit

add $a0, $a0, -1


li $v0, 1 # "print int" system call
syscall

move $t0, $a0


move $a0, $a1
li $v0, 4
syscall

move $a0, $t0


j Loop

Exit: la $a0, msg3

li $v0, 4
syscall
## Exit from program
li $v0, 10 # "Exit" system call
syscall

Type the MIPS code shown above into a text editor. Replace the XXXXXXXXX by your name
and then save the file as "Lab1_1.s" before running it using PCSpim.

Save your code as "Lab1_1.s" and load it into SPIM using "File->Open". Before you run the
program, set register $s1 to some value using "Simulator->Set value...". Then run the program
using "Simulator->Go". If the program does not have any syntax error, the message "successfully
loaded" will appear in the "Messages" window when you load the program. Run your program
and examine the register values.
For this part you may want to check the register values in decimal rather than hexadecimal
format. Under the "Simulator->Settings" menu option, uncheck "General registers in
hexadecimal", if the registers don't show values in decimal format.

Check-off Requirement: Demonstrate your execution with the source code.

4. Translation from C to MIPS [40 points]

Convert the following C program into a MIPS program:

int B[4] = { 300, 200, 100, 0 };


int i = 3;
void main ( void )
{
B[i] = B[0] + B[1] + B[2];
}

This program has two variables, an integer array B and an integer i. It adds the first three array
elements together and stores the result in the last element. To get started, use the following code.

.data 0x10008000 # data segment start (assembler directive)


B: .word 300 # B[0]
.word 200 # B[1]
.word 100 # B[2]
.word 0 # B[3]
i: .word 3
.text # code segment start (assembler directive)
main: la $t1,B # load the address of B[0](&(B[0])== B) into register $t1
lw $t0,0($t1) # load value of B[0] into register $t0
##
## COMPLETE HERE. ##
##
Addi $v0,$0,10 # `exit MIPS program' syscall
syscall

This code gives you a partial solution to the problem. Your task is to complete the program by
adding the missing MIPS instructions. Recall that in MIPS large data structures like arrays are
stored in a memory, not in the registers. To move data from the memory to the register, use the
"load word" instruction (lw). In the above program, "lw $t0, 0($t1)" loads the first array
element (B[0]) to the register $t0. The format of lw is "lw $rt, offset_16bit($rs)", where
$rt is a register to receive data and offset_16bit($rs) has an effective address (EA) (the
address of the word in the memory to be fetched) for data. In MIPS, EA is determined by base
register and offset. Base register ($rs) has a "base address" of the memory. Offset
(offset_16bit) has a 16-bit signed integer.

Here, let's see how to get EA of the first element (B[0]) in array B. In C, you can get EA by
using *B[0] or simply referring to B, the array name without a subscript. In MIPS, we use "load
address" pseudo-instruction, la. In the above program, the instruction after the label main:, "la
$t1, B", shows a pseudo-instruction example. It makes the SPIM assembler load the memory
address of B into register $t1. Then the next instruction "lw $t0, 0($t1)" fetches a word from
memory at location "$t1 + 0". Complete the program for loading the second and third elements
of array B to registers, summing up three values, and store the sum in the forth element of array
B.

Save your code as "Lab1_2.s" and run it in PCSpim.

Check-off Requirement: Allow TA to view your program in the text editor and demonstrate
program execution in SPIM.

 Notes

• .data and .text are assembler directives. They specify which part of the memory will
be used for data or instructions during run-time. Other assembler directives can be found
in below.
• Each element of the array is offset by four bytes, because MIPS uses four bytes (one
word) to store an integer. MIPS memory uses byte addressing.

 MIPS assembler directives

(From Computer Organization and Design - The Hardware/Software Interface by Dave Patterson and John
Hennessy, 3rd edition)

SPIM supports a subset of the assembler directives provided by the actual MIPS assembler:

Align the next datum on a 2n byte boundary.

.align n For example, .align 2 aligns the next value on a word boundary.
.align 0 turns off automatic alignment of .half, .word,
.float, and .double directives until the next .data or
.kdata directive.
.ascii str Store the string in memory, but do not null-terminate it.

.asciiz str Store the string in memory and null-terminate it.

.byte b1,..., bn Store the n values in successive bytes of memory.


The following data items should be stored in the data segment. If the
.data <addr>
optional argument addr is present, the items are stored beginning at
address addr.
.double d1,...,
Store the n floating point double precision numbers in successive
dn memory locations.

Declare that the datum stored at sym is size bytes large and is a
.extern sym size global symbol. This directive enables the assembler to store the
datum in a portion of the data segment that is efficiently accessed via
register $gp.
.float f1,..., fn Store the n floating point single precision numbers in successive
memory locations.
.globl sym Declare that symbol sym is global and can be referenced from other
files.
.half h1,..., hn Store the n 16-bit quantities in successive memory halfwords.

The following data items should be stored in the kernel data segment.
.kdata <addr>
If the optional argument addr is present, the items are stored
beginning at address addr.
The next items are put in the kernel text segment. In SPIM, these
.ktext <addr> items may only be instructions or words (see the .word directive
below). If the optional argument addr is present, the items are stored
beginning at address addr.
.space n Allocate n bytes of space in the current segment (which must be the
data segment in SPIM).
The next items are put in the user text segment. In SPIM, these items
.text <addr> may only be instructions or words (see the .word directive below). If
the optional argument addr is present, the items are stored beginning
at address addr.
Store the n 32-bit quantities in successive memory words. SPIM does
.word w1,..., wn
not distinguish various parts of the data segment (.data, .rdata
and .sdata).

 Control Flow Instructions in MIPS

Type Instruction Description


This instruction jumps unconditionally to the
Unconditional Jump j Label instruction followed by the label Label. It is
equivalent to the goto statement in C.

This instruction branches to label Label, if registers


rs and rt have the same values. In Register Transfer
Notation (RTN), it means:
Conditional Branch
beq rs, rt, Label if ( R[rs] == R[rt] )
on Equality goto Label;

If the registers have different values, the processor


proceeds to the next instruction.

Conditional Branch This instruction branches to label Label, if registers


bne rs, rt, Label
on Inequality rs and rt have the same values.

This instruction sets register rd to 1 if R[rs] <


R[rt]. Otherwise it sets rd to 0. In RTN, it means:

if ( R[rs] < R[rt] )


R[rd] = 1;
Set Register Based on else
slt rd, rs, rt R[rd] = 0;
Relation
There is an immediate version of the slt instruction
in which the 3rd argument is a 16-bit signed integer.
"slti rd, rs, 0x0002" sets rd to 1 if R[rs] <
0x0002.

 I/O Manipulation - MIPS System Calls (syscall)

SPIM provides a set of operating-system-like services through the system call (syscall)
instructions. Basic input and output can be managed and implemented by system calls.

To request a service, a program loads the system call code into register $v0 and arguments into
registers $a0, $a1, $a2, and $a3.

Here is a summary of the system calls for your reference.


Call Code
Service in $v0 Arguments Results

===========================================================================
Print Integer 1 $a0=number
(to be printed)

Example Code:
li $a0, 89
li $v0, 1
syscall
---------------------------------------------------------------------------
Print Float 2 $f12=number
(to be printed)

Example Code:
l.s $f12, flabel
li $v0, 2
syscall

.data
flabel: .float 3.14
---------------------------------------------------------------------------
Print double 3 $f12=number
(to be printed)

Example Code:
l.d $f12, dlabel
li $v0, 3
syscall

.data
dlabel: .double 3.1415926
---------------------------------------------------------------------------
Print String 4 $a0=address
(of string in memory)

Example Code:
la $a0, str1
li $v0, 4
syscall

.data
str1: .asciiz "Hi There!"
---------------------------------------------------------------------------
Read Integer 5 number in $v0
Example Code:
li $v0, 5
syscall
---------------------------------------------------------------------------
Read Float 6 number in $f0
Example Code:
li $v0, 6
syscall
---------------------------------------------------------------------------
Read double 7 number in $f0
Example Code:
li $v0, 7
syscall
---------------------------------------------------------------------------
Read String 8 $a0=address
(of input string in memory)
$a1=length of buffer(n bytes)

Example Code:
la $a0, str1
li $a1, 80
li $v0, 8
syscall

.data
str1: .space 80
---------------------------------------------------------------------------
Sbrk 9 $a0=n-byte address in $v0
(Dynamically (to allocate)
allocate n-byte
of memory) Example Code:
li $a0, 80
li $v0, 9
syscall # Get memory

move $a0, $v0


li $a1, 80
li $v0, 8
syscall # Read String
li $v0, 4
syscall # Print String
---------------------------------------------------------------------------
Exit 10 Example Code:
li $v0, 10
syscall
---------------------------------------------------------------------------

Vous aimerez peut-être aussi