|
This is written as a brief introduction to mips and spim for students
doing the CS75 course project.
MIPS (www.mips.com) is a reduced instruction set computer (RISC), meaning that it contains a small number of simple instructions (x86 is an example of a complex instruction set computer (CISC)) All MIPS instructions are the same size (4 bytes), and there is a simple five stage instruction pipeline. MIPS is a register based architecture, meaning that instruction operands are in registers. Java VM, on the other hand, is a stack based architecture where instruction operands are pushed and poped off an instruction stack. MIPS has a three-address instruction set (instructions have 3 operands). For example: add $t0, $t1, $t2 # add values in reg t1 and t2 and put result in t0MIPS is also a load/store architecture, meaning that values are loaded from memory address into registers and stored from registers to memory address. For example: lw $t5, 4($t1) # load $t5 with the word at mem address 4 + address value stored in register $t1MIPS load and store instructions are the only ones that can directly address memory. MIPS assembelylabelsA label is a string of chars, digits, dot, or underscore charaters, followed by a colon that is on a line by itself. labels are used to associate a name with a line of MIPS code (i.e. an address of an instruction). Some MIPS instructions can have label operands. For example:.L2: # a label ... la $t0, .L2 # load the address assocated with the label .L2 into $t0 ... b .L2 # branch to the instruction at label .L2 assembler directives:These are a subset of the MIPS assembler directives that are used to tell the assembler something about names that are used in a MIPS assembly file:
.text # the succeeding lines contain instructions
.data # the succeeding lines contain data
.globl name # name is global symbol (visible to code in other files)
.asciiz "a string\n" # stores a null terminated string in memory
example:
--------
# single line comments in MIPS start with the '#' character
.text # what follows are instructions
.globl main # main is a global name (can be referenced in other files)
main: # main is a label (a name assoc w/memory location)
sub $sp, $sp, 32
...
loop: # loop is a local label
.data # what follows are data
str: # str is a local label
.asciiz "hello world\n" # this is a string associated with str
registers 32 general purpose registers (32 bits each)
$at, $k0, $k1: reserved for OS and assembler
$a0-$a3: used to pass first 4 arguments to routine (rest passed on stack)
$v0, $v1: used for return values from functions
$t0-$t9: caller-saved registers, used to hold temporaries,
not perserved across calls
$s0-$s7: callee-saved registers, hold long lived data
should be preserved across calls
$gp: global pointer points to middle of 64K block in static data segment
addresses in .data are given relative to it:
lw $v0, 0x20($gp)
$sp: the stack pointer, points to last location on the stack
$fp: frame pointer
$ra: the return address from procedure call
procedure call convention
stack: sp points to the top of the stack (grows into lower addresses)
------
fp points to the bottom of the current stack frame
-----------------
sp --------> local variables
saved registers
-----------------
fp --------> argument 5
argument 6
...
function call:
=============
caller:
------
(1) saves registers a0-a3 and t0-t9 if caller needs their values upon return
callee will assume these are okay to use
(2) sets up arguments
passed arguments: 1st four passed in registers a0-a3
remaining arguments are pushed onto the stack
appear at the begining of the called func's stack frame
(3) execute a jal instruction to jump to address of callee's the first instr
jal saves return address in register $ra
callee:
------
(1) allocate stack memory for the frame (change value of $sp)
(2) save callee-saved registers in the frame
$s0-$s7, $fp, $ra: these are registers the caller expects to be restored
$fp: caller's frame pointer
$ra: return address
others: only if callee uses them
in your code, you will always save all of them
(3) change value of $fp to point to bottom of callee stack frame
function return
===============
callee:
------
(1) return value placed in $v0
(2) restore all callee-saved registers that were saved on func entry
(3) pop the stack frame by adding the frame size to $sp
(4) return by jumping to the address in register $ra
caller:
-------
(1) may "pop" arguments off the stack
MIPS assembley hides some details of real instruction set:
Some MIPS instructionsMIPS is one of the most RISC of the RISC instruction sets, and still we will end up using a subset of its instrutions. Here are some of the instructions you may use:
Arithmetic Instructions
-----------------------
add rd, rs, rt # rd <-- rs + rt
sub rd, rs, rt
mulo rd, rs, rt # rd <-- rs * rt
div rd, rs, rt # rd <-- rs / rt
neg rdest, rsrc # rdest <-- -rsrc
# there are also immediate forms you could use:
ori rd, rs, immed # rd <-- rs || immed
comparison instructions
----------------------
slt rd, rs, rt # rd <-- 1 if rs < rt, 0 otherwise
sle rd, rs, rt # rd <-- 1 if rs <= rt, 0 otherwise
sgt rd, rs, rt # >
sge rd, rs, rt # >=
seq rd, rs, rt # ==
sne rd, rs, rt # !=
branch instructions
-------------------
b label # unconditional branch to label
beq rs, rt, label # conditional branch to label if rs == rt
bgez rs, label # conditional branch to label if rs >= 0
... # and more branch instructions that will be useful
# use branches with other ops to do && || and !
#
# x || y if x is non-zero, then x || y is 1
# else if y is non-zero, then x || y is 1
# else x || y is 0
j target # unconditional jump to instruction at target
jal target # unconitionally jump to instruction at target
# save addresss of next instruction in $ra (func call)
jr rs # jump to instruction whose address is in reg rs
load and store instructions
---------------------------
lb rd, addr # load the byte at addr into $rd
# (see addressing modes below for how addr can be specified)
lw rd, addr # load the word (32 bit value) at addr into $rd
la rd, addr # load the value of addr into $rd (NOT the contents at addr)
li rd, immed # load the value immed into $rd
sb rt, addr # store the low byte from $rt to address addr
sw rt, addr # store the word from $rt to address addr
# example: (global addresses are given as offset from $gp)
lw $t5, 0($gp) # loads global value at offset 0 from gp into t5
la $t4, 0($gp) # loads the address of the global at offset 0
addressing modes:
-----------------
lw rd, imm # load value at address imm
lw rd, ($rs) # load value at address contents of reg rs
lw rd, imm($rs) # load value at address contents of reg rs + imm
li rd, imm # load immediate: load value imm into register rd
data movement instructions
---------------------------
move rd, rs # move value in register rs to rd
SPIMSpim (pages.cs.wisc.edu/~larus/spim.html) is a MIPS simulator. Input to spim is a MIPS assembly file that spim will execute.some of the things that spim and xspim support that we will use:
|