Lecture 3 - TAMU Computer Science Faculty Pages

Download Report

Transcript Lecture 3 - TAMU Computer Science Faculty Pages

MIPS Assembly Language I
Computer Architecture
CPSC 321
Andreas Klappenecker
MIPS
The MIPS assembly language has
• arithmetic instructions (add, sub,…)
• logical instructions (and, or,…)
• branch instructions (bgtz, bne, …)
• jump instructions (j, jr, …)
• load and store instructions (lb, sw,…)
• floating point instructions
MIPS Instructions and Registers
The operands to arithmetic instructions cannot
be arbitrary expressions like in high-level
languages, but have to be registers.
add $t0, $t1, $t2 # $t0=$t1+$t2
Registers are special locations of memory that
are also visible to the programmer. The size of
a register is 32 bits in the MIPS architecture.
MIPS Design Principles
1. Simplicity favors regularity
(instructions have exactly three operands)
2. Smaller is faster
(do not provide too many registers)
3. Good design demands good compromises
(all instructions have the same length, but three
different formats)
MIPS Datapath
Instruction Word Formats
• Register format
op-code
rs
6
rt
5
rd
5
shamt
5
funct
5
6
• Immediate format
op-code
rs
6
rt
5
immediate value
5
16
• Jump format
op-code
6
26 bit current segment address
26
Instruction Format Examples
• Register Format
• add $t0, $t1, $t2
• Immediate Format
• addi $t0, $t1, 10
• Jump Format
• j label
Hello World!
.text
# code section
.globl main
main:
li $v0, 4
# system call for print string
la $a0, str
# load address of string to print
syscall
# print the string
li $v0, 10
# system call for exit
syscall
# exit
.data
str:
.asciiz “Hello world!\n” # NUL terminated string, as in C
Memory Organization
0x7fff ffff
Stack segment
Dynamic data
0x1000 0000
Static data
Text segment
0x40 0000
Reserved
The memory is byte
addressed. If you want to
step word by word through
the memory, then you have
to increase your “pointer”
each time by 4.
Data segment
Addressing modes
lw $s1, 8($s0)
# $s1 = Mem[$s0+8]
The register $s0 contains the base address. We can
access the address by ($s0) and add an offset 8($s0);
this will be useful for procedures that have to save
registers on the stack.
Increase array elements by 5
.text
.globl main
main:
loop:
la
$t0, Aaddr
# $t0 = pointer to array A
lw
$t1, len
# $t1 = length (of array A)
sll
$t1, $t1, 2
# $t1 = 4*length
add
$t1, $t1, $t0
# $t1 = address(A)+4*length
lw
$t2, 0($t0)
# $t2 = A[i]
addi $t2, $t2, 5
# $t2 = $t2 + 5
sw
# A[i] = $t2
$t2, 0($t0)
addi $t0, $t0, 4
# i = i+1
bne
# if $t0<$t1 goto loop
$t0, $t1, loop
.data
Aaddr:
.word 0,2,1,4,5
len:
.word 5
# array with 5 elements
MIPS Registers
The MIPS architecture has 32 registers
with 32 bits each, $0,…,$31.
The MIPS assembly language provides
more convenient symbolic names.
The register usage follows certain
conventions that you need to memorize.
MIPS Registers
•
•
•
•
•
•
•
•
•
$zero contains the constant 0
$at is reserved for the assembler – do not use
$v0 and $v1 contain results of procedure call
$a0,…,$a3 contain arguments of procedure calls
$t0,…,$t9 temporary registers (which are not preserved after
a procedure call; caller needs to save these registers)
$s0,…,$s7 temporary registers (by convention preserved after
procedure call; callee needs to save these registers)
$k0, $k1 reserved – do not use
$gp, $sp, $fp global area, stack pointer, frame pointer
$ra return address (used by a procedure call)
We come back to these conventions!
Register Conventions
• Suppose you store the value 7 in $s3 and call
a procedure. Does $s3 still contain 7 after
the procedure call?
• Yes, it should (if the procedure is using $s3, then
it is supposed to save its value, and has to restore
the value of $s3 before returning)
• Suppose you store the value 7 in $t3 and call
a procedure. Does $t3 still contain 7 after
the procedure call?
• No, not necessarily. The variable $t3 is temporary
and the procedure is allowed to overwrite this
register and does not have to restore its value.
Procedures
• jal addr
• store address + 4 into $ra
• jump to address addr
• jr $ra
• allows subroutine to jump back
• care must be taken to preserve $ra!
• more work for non-leaf procedures
Procedures
• Procedures are one of the few means to
structure your assembly language program
• Program small entities that can be tested
separately
• Procedures can make an assembly program
more readable
• Recursive procedures sometimes elegantly
solve problems.
Write your own procedures
# prints the integer contained in $a0
print_int:
li $v0, 1
# system call to
syscall
# print integer
jr $ra
# return
main: . . .
li $a0, 10
# we want to print 10
jal print_int
# print integer in $a0
Write your own procedures
.data
linebrk: .asciiz “\n”
.text
print_eol:
# prints "\n"
li $v0, 4
#
la $a0, linebrk
#
syscall
#
jr $ra
# return
main: . . .
jal print_eol
# printf(“\n”)
Write your own procedures
.data
main:
loop:
li $s0, 1
# $s0 = loop ctr
li $s1, 10
# $s1 = upperbnd
move $a0, $s0
# print loop ctr
jal print_int
#
jal print_eol
# print "\n"
addi $s0, $s0, 1
# loop ctr +1
ble $s0, $s1, loop
# unless $s0>$s1…
Non-leaf procedures
• Suppose that a procedure procA calls another
procedure, jal procB
• What kind of problem occurs?
• Problem: jal stores the return address of
procedure procB and destroys return address
of procedure procA
• Save $ra and all necessary variables onto the
stack, call procB, and then restore.
Stack
The stack can be used for
 parameter passing
 storing return addresses
$sp = $sp - 12
high address
4($sp)
 storing result variables
The stack pointer is
contained in register $sp.
8($sp)
stack pointer $sp -> 0($sp)
low address
Memory Organization
0x7fff ffff
Stack segment
Dynamic data
0x1000 0000
Static data
Text segment
0x40 0000
Reserved
The memory is byte
addressed. If you want to
step word by word through
the memory, then you have
to increase your “pointer”
each time by 4.
Data segment
Fibonacci
fib(0) = 0
fib(1) = 1
fib(n) = fib(n-1) + fib(n-2)
0, 1, 1, 2, 3, 5, 8, 13, 21,…
Fibonacci
li $a0, 10
# call fib(10)
jal fib
#
move $s0, $v0
# $s0 = fib(10)
fib is a recursive procedure with one argument $a0
need to store argument $a0, temporary register $s0 for
intermediate results, and return address $ra
fib:
gen:
rreg:
sub $sp,$sp,12
# save registers on stack
sw $a0, 0($sp)
# save $a0 = n
sw $s0, 4($sp)
# save $s0
sw $ra, 8($sp)
# save return address $ra
bgt $a0,1, gen
# if n>1 then goto generic case
move $v0,$a0
# output = input if n=0 or n=1
j rreg
# goto restore registers
sub $a0,$a0,1
# param = n-1
jal fib
# compute fib(n-1)
move $s0,$v0
# save fib(n-1)
sub $a0,$a0,1
# set param to n-2
jal fib
# and make recursive call
add $v0, $v0, $s0
# $v0 = fib(n-2)+fib(n-1)
lw
$a0, 0($sp)
# restore registers from stack
lw
$s0, 4($sp)
#
lw
$ra, 8($sp)
#
add $sp, $sp, 12
jr $ra
# decrease the stack size
Practice, practice, practice!!!
• Read Chapter 3 and Appendix A
• Write many programs and test them
• Get a thorough understanding of all
assembly instructions
• Study the register conventions
carefully
SPIM system calls
procedure
print int
print float
print double
print string
code $v0
argument
$a0 contains number
1
$f12 contains number
2
$f12 contains number
3
$a0 address of string
4
SPIM system calls
procedure
code $v0
result
read int
5
res returned in $v0
read float
6
res returned in $f0
read double
7
res returned in $f0
read string
8