## LSU EE
3755 -- Fall 2003 -- 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