## LSU EE 3755 --
Fall 2009 -- Computer
Organization
#
## MIPS Notes 4 -- Load and Store
Instructions
#
## Contents
#
# Load Byte (Unsigned)
# Store Byte
# Load Byte
# Load Word, Store Word
# Load and Store Half
# Array Access Examples
# Histogram Program
## References
#
# :PH:
Patterson & Hennessy, "Computer Organization &
Design"
# :Mv1: MIPS Technologies, "MIPS32 Architecture for
Programmers Vol I: Intro"
# :Mv2: MIPS Technologies, "MIPS32 Architecture for
Programmers Vol II: Instr"
################################################################################
## Load Byte (Unsigned)
# :Syntax: LBU rt, offset(rs)
# Load Byte Unsigned
#
rt <- { 24'b0, Mem[ rs + offset ] }
#
Note: rs and rt are registers.
#
Offset is a 16-bit immediate
#
sign extended.
# :Example:
#
# Simple uses of lbu.
#
Initially: $a2 <-- 0x0000 1000
# At
Mem[ 0x0000 1004 ] = 0x12
#
lbu
$a0, 4($a2)
#
#
Effective address is 4 + 0x0000 1000 = 0x0000 1004.
#
$a0 loaded with 0x0000 0012.
addi
$a2, $a2, 4 # $a2 <-
0x0000 1004
lbu
$a0, 0($a2)
#
#
Effective address is 0 + 0x0000 1004 = 0x0000 1004 (same as
above.)
#
$a0 loaded with 0x0000 0012 (again)
####
# :Example:
#
# Procedure to determine the length of a C-style
string.
Includes
# code to call the
procedure.
.data
str:
.asciiz "EE3755 is probably a cool class ."
msg:
.asciiz "The length of string \n \"%/a1/s\"\nis
%/v1/d.\n"
.text
.globl __start
__start:
la
$a0, str
# Load address of string.
jal
strlen
# Call strlen procedure.
nop
addi
$a1, $a0, 0 # Move address of string to
$a1
addi
$v1, $v0, 0 #
Move length of string to $v1
addi
$v0, $0, 11 #
System call code for message.
la
$a0, msg
# Address of message.
syscall
addi
$v0, $0, 10 #
System call code for exit.
syscall
strlen:
##
Register Usage
#
#
$a0: Address of first character of string.
#
$v0: Return value, the length of the string, $v0 holds the length of the
string.
#
#
$t0: Character being examined.
#
$t1: Address of current character being examined.
#
addi
$t1, $a0, 0
LOOP:
lbu
$t0, 0($t1)
addi
$t1, $t1, 1
bne
$t0, $0, LOOP
nop
addi
$t1, $t1, -1
jr
$ra
sub
$v0, $t1, $a0
####
# Why
addi $t1, $t1, -1 ?
# Look at a memory location . we assume only
"EE3755\0".
#
Memory
#
msg:
#
0x1000
E
#
0x0001
E
#
0x0002
3
#
0x0003
7
#
0x0004
5
#
0x0005
5
#
0x0006
\0
# program at strlen
procedure.
#
t1 = 1000, t0 =
E
#
t1 =1001 t0 = E
# .......(assume it repeats till it
loads "5".
#
t1 =1005 t0 = 5
# t1 =
1006 t0 = \0 (now load
null).
# t1 =
1007 # addi $t1,$t1, 1 //
increments address by one
#
although the character is null
#
# so we have to decrement by one
# t1 =
1006. t1 - a0 = 6 ==> v0..
#
so $v0 holds the length of
the string.
################################################################################
## Store Byte
# :Syntax: SB rt, offset(rs)
# Store Byte
#
Mem[ rs + offset ] = rt[7:0]
# :Example:
#
# Simple uses of sb.
#
Initially: $a2 <- 0x0000 1004
# At
Mem[ 0x0000 1004 ] = 0
#
addi
$t0, $0, 0x14 # t0
<- 0x0000 0014
sb
$t0, 0($a2)
#
#
Effective address is 0 + 0x0000 1004 = 0x0000 1004
#
0x14 written to Mem[ 0x0000 1004 ]
addi
$t0, $0, 0x1234 # t0 <-
0x0000 1234
sb
$t0, 0($a2)
#
#
Effective address is 0 + 0x0000 1004 = 0x0000 1004
#
0x34 written to Mem[ 0x0000 1004 ]
#
Note that only bits 7:0 of $t0 written to memory.
####
# :Example:
#
# Program to convert a C-style string to upper
case.
.data
str:
.asciiz "Hello, world!"
before:
.asciiz "Before: %/s1/s\n"
after:
.asciiz "After:
%/s1/s\n"
.text
.globl __start
__start:
la
$s1, str
la
$a0, before
addi
$v0, $0, 11
syscall
jal
upper
add
$a0, $s1, $0
la
$a0, after
addi
$v0, $0, 11
syscall
li
$v0, 10
syscall
upper:
##
Register Usage
#
#
$a0: Address of string to convert.
#
#
$a0: Address of character being examined.
#
$t1: Character being examined.
#
$t2: Comparison result.
#
Check whether the character is upper case or
not.
LOOP:
lbu
$t1, 0($a0)
addi
$a0, $a0, 1
beq
$t1, $0, DONE
slti
$t2, $t1, 97 # < 'a' //
not a lower case.
bne
$t2, $0 LOOP
slti
$t2, $t1, 123 # 'z' + 1 // 97-122 lower case.
beq
$t2, $0, LOOP# $t2 =1 means , character is lower case.
addi
$t1, $t1, -32 # change to
upper case.
j
LOOP
sb
$t1,-1($a0) #because of addi
$a0,$a0,1
DONE:
jr
$ra
nop
####
## put
ASCII table here
##
################################################################################
## Load Byte
# :Syntax: LB rt, offset(rs)
# Load Byte
#
rt <- sign_extend( Mem[ rs + offset ] );
#
Note: rs and rt are registers.
#
Offset is a 16-bit
immediate.
# :Example:
#
#
# Initially: $a2 <- 0x0000
1000
# At Mem[ 0x0000 1000 ] = 0x12 // 12 = 0001
0010
# At Mem[ 0x0000 1001 ] = 0x7f // 7f
= 0111 1111
# At Mem[ 0x0000 1002 ] = 0x80 // 80 = 1000 0000 (negative #)
# At Mem[ 0x0000 1003 ] = 0xff // ff = 1111 1111 (negative
#)
#
lb
$t0, 0($a2) # $t0 <- 0x0000
0012
18
lb
$t1, 1($a2) # $t1 <- 0x0000
007f
127
lb $t2,
2($a2) # $t2 <- 0xffff ff80 (-128)
lb
$t3, 3($a2) # $t3 <- 0xffff
ffff (-1)
####
##
Usage
#
# lbu:
Characters, unsigned integers.
# lb:
Signed integers.
################################################################################
## Load Word, Store Word
##
Note
#
# Each memory location holds 8
bits.
# Register size: 32 bits.
#
# To load a register use lw (load
word).
# Loads for consecutive bytes into a
register.
# :Syntax: LW rt,
offset(rs)
#
rt <- { Mem[ rs + offset + 3 ], Mem[ rs + offset + 2
],
#
Mem[ rs + offset + 1 ], Mem[ rs + offset + 0 ] }
#
#
Load register rt with four bytes of memory starting at
address
#
rs + offset.
#
Address rs + offset must be a multiple of 4.
# :Example:
#
#
Assume: $a2<- 0x0000 1004
# At
Mem[ 0x0000 1004 ] = 0x00003755
#
More precisely: (Little Endian) //$$
# Mem[ 0x0000 1007 ] =
0x00
# Mem[ 0x0000 1006 ] =
0x00
# Mem[ 0x0000 1005 ] =
0x37
# Mem[ 0x0000 1004 ] =
0x55
#
lw
$a0, 0($a2)
#
0x0000 3755 loaded into $a0
lw
$a0, 2($a2) #
Error
#
Effective address = 0x0000 1006, not a multiple of 4
addi
$a2, $a2, -2
lw
$a0, 2($a2) # No
problem
#
Effective address = 0x0000 1004, is a multiple of 4
# :Example:
#
.data
my_word:
.word 123
.word 456
.text
la
$t0, my_word
lw
$t1, 0($t0) # t1 <-
123
lw
$t2, 4($t0) # t2 <-
456
addi
$t0, $t0, 4
lw
$t3, 0($t0) # t3 <-
456 (Another way to load
456)
addi
$t0, $t0, 4
lw
$t4, -4($t0) # t4 <-
456 (And another way to load
456)
# Error, instruction will never finish because
address not a multiple of 4.
lw
$t9, 1($t0)
####
# :Syntax: SW rt,
offset(rs)
#
Mem[ rs + offset+ 3 ] =
rt[31:24]
#
Mem[ rs + offset + 2 ] = rt[23:16]
#
Mem[ rs + offset + 1 ] = rt[15:8]
#
Mem[ rs + offset + 0 ] = rt[7:0]
#
Write memory starting at address offset + rs with contents of
rt.
#
Effective address, rs + offset, must be a multiple of
4.
# :Example:
#
#
Assume: $a2, <- 0x0000 1004
# At
Mem[ 0x0000 1004 ] = 0x00003755
#
More precisely: (Little Endian)
# Mem[ 0x0000 1007 ] =
0x00
# Mem[ 0x0000 1006 ] =
0x00
# Mem[ 0x0000 1005 ] =
0x37
# Mem[ 0x0000 1004 ] =
0x55
#
lui
$a0, 0x1234
ori
$a0, $a0, 0x5678 # $a0 <-
0x12345678
sw
$a0, 0($a2)
# Mem[ 0x0000 1007 ] =
0x12
# Mem[ 0x0000 1006 ] =
0x34
# Mem[ 0x0000 1005 ] =
0x56
# Mem[ 0x0000 1004 ] =
0x78
lbu
$t0, 3($a2) # $t0 <- 0x0000
0012
lbu
$t1, 2($a2) # $t1 <- 0x0000
0034
lbu
$t2, 1($a2) # $t2 <- 0x0000
0056
lbu
$t3, 0($a2) # $t3 <- 0x0000
0078
lw
$a0, 2($a2) #
Error
#
Effective address = 0x1006, not a multiple of 4
addi
$a2, $a2, -2
lw
$a0, 2($a2) # No
problem
#
Effective address = 0x1004, is a multiple of 4
####
################################################################################
## Load and Store Half
# :Syntax: LH rt, offset(rs)
# Load Half
#
rt <- sign_extend( { Mem[ rs + offset + 1 ], Mem[ rs + offset] }
)
#
Load register rt with two bytes of memory starting at
address
# rs +
offset.
#
Address rs + offset must be a multiple of 2.
#
# :Syntax: LHU rt, offset(rs)
# Load Half Unsigned
#
rt <- { 16'b0, Mem[ rs + offset +1], Mem[ rs + offset]
}
#
Load register rt with two bytes of memory starting at
address
#
rs + offset.
#
Address rs + offset must be a multiple of 2.
#
# :Syntax: SH rt, offset(rs)
# Store Half
#
Mem[ rs + offset + 1 ] = rt[15:8]
#
Mem[ rs + offset + 0 ] = rt[7:0]
#
Effective address, rs + offset, must be a multiple of
2.
################################################################################
## Array Access Examples
# :Example:
#
# Array accesses. In most examples i is the index (the
number of the
# element to load). Note that i must be multiplied by the
size of the
# element before adding it on to the address of the
first element.
#
# Registers:
a, s1; b, s5; s, s2; us, s3; c, s4; i, t0; x, t1
#
char *c; ...
# $s4 = c; $t0 =
i
# x
= c[i];
#
add
$t5, $s4, $t0 # $t5 <-
&c[i] (Address of
c[i].)
lb
$t1, 0($t5)
# x = c[i]; $t1 <-
c[i]
#
char *c; ...
# $s4 = c; $t0 =
i
# x
= c[i+1] + c[i+2];
#
#
beginner's way to compile above code(not
efficient).
#
pay attention to the addressing mode.
addi
$t2,$t0,1
#i+1;
add $t5, $s4, $t2 #
$t5 <- &c[i+1] (Address of
c[i+1].)
lb $t6,0($t5)
# t6<=
c[i+1]
addi $t3,$t0,2
# i +2;
add $t5,$s4,$t3
#$t5 <-&c[i+2]
lb $t7,0($t5)
# t7 <= c[i+2]
add $t1,$t6,$t7
# x = c[i+1]+c[i+2]
# so
7 lines of code. see below a little bit better use of
#
addressing mode(4 lines)
add
$t5, $s4, $t0 # $t5 <-
&c[i] (Address of
c[i].)
lb
$t6, 1($t5)
# $t6 <-
c[i+1]
lb
$t7, 2($t5)
# $t7 <- c[i+2]
add
$t1, $t6, $t7 # x = c[i+1] +
c[i+2]
#
int *a; ...
# $s1 = a; $t0 =
i
# x
= a[i];
sll
$t5, $t0, 2 # $t5
<- i * 4; Each element is four
characters.
add
$t5, $s1, $t5 # $t5 <-
&a[i] (Address of
a[i].)
lw
$t1, 0($t5)
# x = a[i]; $t1 <-
a[i]
#
int *a; ...
# $s1 = a; $t0 =
i
# x
= a[i+1] + a[i+2];
#
sll
$t5, $t0, 2 # $t5
<- i * 4; Each element is four
characters.
add
$t5, $s1, $t5 # $t5 < -
&a[i] (Address of
a[i].)
lw
$t6, 4($t5)
# $t6 <- a[i+1]
lw
$t7, 8($t5)
# $t7 <- a[i+2]
add
$t1, $t6, $t7 # x = a[i+1] +
a[i+2]
#
int x, j, *a, *b; # $t1 = x; $t2 =
j; $s1 = a; $s2 = b
# j
= 3;
# b
= a + j; //pay
attention to this add operation
#
// if a = 0x1000 and j = 3, then b= a+j
#
//
which will NOT be 1003
= 1000 +
3.
#
// since a is pointer, we should add like this
following:
#
// 1000( a) + 3(j) * size of
varialbe.
#
// so a+j = 1000 + 3 *
4;
#
//
a+j = 100c.
# x
= *b; // x
= a[3];
addi
$t2, $0, 3 # j =
3;
sll
$t5, $t2, 2 # $t5 <- j *
4
add
$s5, $s1, $t5 # b = a +
j;//address of a[3]
lw
$t1, 0($s5)
# x = *b = a[j] =
a[3]
#
short *s; ... #
$s2 = s; $t0 = i // short is 2bytes
long.
# x
= s[i];
#
sll
$t5, $t0, 1 # $t5
<- i * 2; Each element is two
characters.
add
$t5, $s2, $t5 # $t5<- &s[i] (Address of
s[i].)
lh
$t1, 0($t5)
# x = s[i]; $t1<-
s[i]
#
$s3 = us; $t0 =
i
#
unsigned short *us;
# x = us[i];
#
sll
$t5, $t0, 1 # $t5
<- i * 2; Each element is two
characters.
add
$t5, $s3, $t5 # $t5 <-
&us[i] (Address of
us[i].)
lhu
$t1, 0($t5)
# x = us[i]; $t1 <-
us[i]
# using "lhu" instead of "lh"
####
################################################################################
## Histogram Program
##
Histogram Program.
#
# Computes how many times each letter appears in a
string.
#
# For example, for the following
string:
#
# We
hold these truths to be self-evident that all men are
created
# equal,
that they are endowed by their Creator with certain
unalienable
#
Rights, that among these are Life, Liberty, and the pursuit
of
#
Happiness. That to secure these rights, Governments are
instituted
# among
Men, deriving their just powers from the consent of
the
#
governed. That whenever any
Form of Government becomes destructive of
# these
ends, it is the Right of the People to alter or to abolish
it,
# and to
institute new Government, laying its foundation on
such
#
principles and organizing its powers in such form, as to them
shall
# seem
most likely to effect their Safety and Happiness
#
# The program would generate the counts shown
below:
#
# Letter
A count: 33 ( 5.05)
****************
# Letter
B count: 6 ( 0.92) ***
# Letter
C count: 11 ( 1.68) *****
# Letter
D count: 15 ( 2.30) *******
# Letter
E count: 77 ( 11.79)
**************************************
# Letter
F count: 14 ( 2.14) *******
# Letter
G count: 13 ( 1.99) ******
# Letter
H count: 32 ( 4.90)
****************
# Letter
I count: 36 ( 5.51)
******************
# Letter
J count: 1 ( 0.15)
# Letter
K count: 1 ( 0.15)
# Letter
L count: 18 ( 2.76)
*********
# Letter
M count: 14 ( 2.14) *******
# Letter
N count: 39 ( 5.97)
*******************
# Letter
O count: 36 ( 5.51)
******************
# Letter
P count: 11 ( 1.68) *****
# Letter
Q count: 1 ( 0.15)
# Letter
R count: 34 ( 5.21)
*****************
# Letter
S count: 36 ( 5.51)
******************
# Letter
T count: 65 ( 9.95)
********************************
# Letter
U count: 13 ( 1.99) ******
# Letter
V count: 8 ( 1.23) ****
# Letter
W count: 7 ( 1.07) ***
# Letter
Y count: 7 ( 1.07) ***
# Letter
Z count: 1 ( 0.15)
#
# For
Example:
# Memory :
# 0x1000
:
W
# 0x1001
:
e
# 0x1002
:
# 0x1003
:
h
# 0x1004
:
o
# 0x1005
:
l
# 0x1006
:
d
....
....
# str <=0x1000;
# Table :
//we assume 0x
7000;
# 0x 7000
# 0x 7001
# 0x 7002
# 0x 7003
//we save int: the
number of occurence of "A"
# 0x 7004
# 0x 7005
# 0x 7006
# 0x 7007
// the number of
occurence of "B"
..
..
.......
# 0x 7058
// the
number of occurence of "W"
#
#
(c ="W") -'A'
#
87 - 65
#
index <= 22. 22 * 4=
88(decimal)
#
88 = 0x58
#
table[index]++;
..
# Here is such a histogram procedure written in
C:
#
#
# Unoptimized:
#
# void
# histo(char *str, int
*table)
# {
#
upper(str);
#
#
for(; *str; str++)
#
{
# char
c =
*str;
# int index
= c - 'A';
#
# if( index
>= 0 && index <= 25 )
#
table[ index ]++;
#
}
# }
#
#
# Optimized:
#
# void
# histo2(unsigned char *str, int
*table)
# {
#
upper(str);
#
#
for(; *str; str++)
#
{
# unsigned
int index = *str - 'A';
#
# if( index
< 26 )
#
table[ index ]++;
#
#
}
# }
#
#
# The assembler version of the procedure is to be
called with register
# $a0 set to the address of the first character of
the string and $a1
# set to the address of the first element of the
histogram table.
#
# The code below is just the histogram
procedure. The
program
# used to generate the table above is at the end of this
notes.
histo:
##
Register Usage
#
#
Call: $a0 String to
analyze.
#
$a1 Address of table. Each element is an
integer.
addi
$s0, $ra, 0 # Make a
copy of the return address.
jal
upper
# Convert to upper case.
addi
$t0, $a0, 0 # Make a
copy of string start address.
addi
$ra, $s0, 0 # Restore
return address.
LOOP:
lbu
$t1, 0($t0) #
Load a character.
addi
$t0, $t0, 1 # Increment
address.
beq
$t1, $0, DONE # Check for
null termination.
addi
$t1, $t1, -65 # Set $t1 to table
index. ( A->0, B->1, etc.)
sltiu $t2, $t1, 26 #
If $t1 is >= 26 then it's not a letter.
beq
$t2, $0, LOOP # Note that
comparison above is unsigned.
sll
$t1, $t1, 2 #
Scale index.
add
$t3, $a1, $t1 # Add index on
to address of first element
lw
$t4, 0($t3)
# Load histogram entry.
addi
$t4, $t4, 1
j
LOOP
sw
$t4, 0($t3)
# Store the incremented value.
DONE:
jr
$ra
nop
####
# Assembly language generated by gcc for unoptimized
version:
#
# Comment text in square brackets describe activities
not covered in 3755.
#
$Lscope0:
.align
2
.globl
histo
.text
$LM6:
# hist.c:11: {
.ent
histo
histo:
.frame
$sp,32,$ra
# vars= 0, regs= 3/0, args= 16, extra= 0
.mask
0x80030000,-8
.fmask
0x00000000,0
$LBB2:
subu $sp,$sp,32 # [Increment
stack pointer.]
sw
$s0,16($sp)
# [Save register s0, restored before return.]
move
$s0,$a0
sw
$s1,20($sp)
# [Save register s1, restored before return.]
sw
$ra,24($sp)
# [Save register ra, restored before return.]
$LM7:
# hist.c:12:
upper(str);
.set
noreorder
.set
nomacro
jal
upper
move $s1,$a1
# Make a copy of $a1.
.set
macro
.set
reorder
$LM8:
# hist.c:14: for(; *str;
str++)
lb
$v0,0($s0)
# Load first character of string, sign
extended.
lbu
$a0,0($s0)
# Load first character of string again.
.set
noreorder
.set
nomacro
beq
$v0,$zero,$L26
sll
$a3,$a0,24
# First of two instructions to sign-extend
.set
macro
# loaded character. (I don't know why
.set
reorder
# compiler didn't just use $v0.)
$LBB3:
$LM9:
# hist.c:16: char
c =
*str;
$L27:
sra
$v1,$a3,24
# Finish sign extension.
$LM10:
# hist.c:17: int index
= c - 'A';
addu
$a1,$v1,-65
sll
$a2,$a1,2
$LM11:
# hist.c:19: if( index
>= 0 && index <= 26 )
sltu
$a0,$a1,27
# Note: unsigned comparison, so no need
# to check for index >= 0.
$LM12:
# hist.c:16: char
c =
*str;
addu $s0,$s0,1 # This is
really : str++
$LM13:
# hist.c:19: if( index
>= 0 && index <= 26 )
.set
noreorder
.set
nomacro
beq
$a0,$zero,$L11
addu $v1,$a2,$s1 # $v1 ->
&table[ index ];
.set
macro
.set
reorder
$LM14:
# hist.c:20:
table[ index ]++;
lw
$t1,0($v1)
#nop
addu
$t0,$t1,1
sw
$t0,0($v1)
$LBE3:
$LM15:
# hist.c:14: for(; *str;
str++)
$L11:
lb
$t2,0($s0)
# Load character of string, sign extended.
lbu
$a0,0($s0)
# Load character of string again.
.set
noreorder
.set
nomacro
bne
$t2,$zero,$L27
sll
$a3,$a0,24
# First of two instructions to sign-extend
.set
macro
# loaded character. (I don't know why
.set
reorder
# compiler didn't just use $t2.)
$L26:
lw
$ra,24($sp)
# [Restore saved $ra]
lw
$s1,20($sp)
# [Restore saved $s1]
lw
$s0,16($sp)
# [Restore saved $s0]
#nop
.set
noreorder
.set
nomacro
j
$ra
addu $sp,$sp,32 # [Restore stack
pointer.]
.set
macro
.set
reorder
$LBE2:
.end
histo
#############################################
##complete code for histogram and generating
table
.data
doi:
.ascii "We hold these truths to be self-evident that all men
"
.ascii "are created equal, that they are endowed by their
"
.ascii "Creator with certain unalienable Rights, that among
"
.ascii "these are Life, Liberty, and the pursuit of
"
.ascii "Happiness. That to secure these rights, Governments
"
.ascii "are instituted among Men, deriving their just powers
"
.ascii "from the consent of the governed. That whenever any
"
.ascii "Form of Government becomes destructive of these ends,
"
.ascii "it is the Right of the People to alter or to abolish
"
.ascii "it, and to institute new Government, laying its
"
.ascii "foundation on such principles and organizing its
"
.ascii "powers in such form, as to them shall seem most likely
"
.asciiz "to effect their Safety and Happiness
"
msg:
.asciiz "Letter %/t3/c
count: %/t1/3d (%/f4/6.2f%%) %/t5/s\n";
.align 4
histogram_data:
.space 104
stars:
.space
40
.text
.globl __start
__start:
la $a0, doi
la $a1, histogram_data
addi
$t1, $a1, 0
addi
$t2, $t1, 100
L3:
sw
$0, 0($t1)
bne
$t1, $t2, L3
addi
$t1, $t1, 4
la $t1, stars
addi
$t2, $t1, 40
addi
$t3, $0, 42 #
'*'
L4:
sb
$t3, 0($t1)
bne
$t1, $t2, L4
addi
$t1, $t1, 1
sb
$0, 0($t1)
jal
strlen
nop
mtc1
$v0, $f2
cvt.d.w $f2, $f2
addi $v0, $0,
100
mtc1
$v0, $f4
cvt.d.w $f4, $f4
div.d $f2, $f4, $f2
jal
histo
nop
add
$t0, $0, $0
addi
$t3, $0, 64
addi
$t4, $t3, 26
la $s1, histogram_data
addi
$v0, $0, 11
la $s2, stars
addi
$s2, $s2, 41
L2:
lw
$t1, 0($s1)
addi
$s1, $s1, 4
beq
$t1, $0, TEST
addi
$t3, $t3, 1
srl
$t6, $t1, 1
sub
$t5, $s2, $t6
mtc1
$t1, $f0
cvt.d.w $f0, $f0
mul.d $f4, $f0,
$f2
syscall
TEST:
bne
$t3, $t4, L2
nop
addi
$v0, $0, 10
syscall
################################################################################
## histo: Compute Character Usage
Histogram
histo:
##
Register Usage
#
#
Call: $a0 String to
analyze.
#
$a1 Address of table. Each element is an
integer.
addi
$s0, $ra, 0 # Make a
copy of the return address.
jal
upper
# Convert to upper case.
addi
$t0, $a0, 0 # Make a
copy of string start address.
addi
$ra, $s0, 0 # Restore
return address.
LOOP:
lbu
$t1, 0($t0) #
Load a character.
addi
$t0, $t0, 1 # Increment
address.
beq
$t1, $0, DONE # Check for
null termination.
addi
$t1, $t1, -65 # Set $t1 to table
index. ( A->0, B->1, etc.)
sltiu $t2, $t1, 26 # If $t1
is >= 26 then it's not a letter.
beq
$t2, $0, LOOP # Note that
comparison above is unsigned.
sll
$t1, $t1, 2 #
Scale index.
add
$t3, $a1, $t1 # Add index on
to address of first element
lw
$t4, 0($t3)
# Load histogram entry.
addi
$t4, $t4, 1
j
LOOP
sw
$t4, 0($t3)
# Store the incremented value.
DONE:
jr
$ra
nop
################################################################################
## upper: Convert to Upper
Case
upper:
##
Register Usage
#
#
$a0: (Call) Address of string to convert.
#
#
$a0: Address of character being examined.
#
$t1: Character being examined.
#
$t2: Comparison result.
ULOOP:
lbu
$t1, 0($a0)
addi
$a0, $a0, 1
beq
$t1, $0, UDONE
slti
$t2, $t1, 97 # < 'a'
bne
$t2, $0 ULOOP
slti
$t2, $t1, 123 # 'z' + 1
beq
$t2, $0, ULOOP
addi
$t1, $t1, -32
j
ULOOP
sb
$t1,-1($a0)
UDONE:
jr
$ra
nop
################################################################################
## strlen: String
Length
strlen:
##
Register Usage
#
#
$a0: Address of first character of string.
#
$v0: Return value, the length of the string.
#
#
$t0: Character being examined.
#
$t1: Address of current character being examined.
#
addi
$t1, $a0, 0
SLOOP:
lbu
$t0, 0($t1)
bne
$t0, $0, SLOOP
addi
$t1, $t1, 1
addi
$t1, $t1, -1
jr
$ra
sub
$v0, $t1, $a0