## LSU EE 3755 --10/13 Fall 2004 -- Computer Organization

#

## MIPSNotes 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

 

####

# Whyaddi $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:(LittleEndian)//$$

������� #�� 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:(LittleEndian)

������� #�� 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'sway to compileabove 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 be1003 =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 Acount:33 (5.05) ****************

#Letter Bcount:�� 6 (0.92) ***

#Letter Ccount:11 (1.68) *****

#Letter Dcount:15 (2.30) *******

#Letter Ecount:77 ( 11.79) **************************************

#Letter Fcount:14 (2.14) *******

#Letter Gcount:13 (1.99) ******

#Letter Hcount:32 (4.90) ****************

#Letter Icount:36 (5.51) ******************

#Letter Jcount:�� 1 (0.15)

#Letter Kcount:�� 1 (0.15)

#Letter Lcount:18 (2.76) *********

#Letter Mcount:14 (2.14) *******

#Letter Ncount:39 (5.97) *******************

#Letter Ocount:36 (5.51) ******************

# Letter Pcount:11 (1.68) *****

#Letter Qcount:�� 1 (0.15)

#Letter Rcount:34 (5.21) *****************

#Letter Scount:36 (5.51) ******************

#Letter Tcount:65 (9.95) ********************************

#Letter Ucount:13 (1.99) ******

#Letter Vcount:�� 8 (1.23) ****

#Letter Wcount:�� 7 (1.07) ***

#Letter Ycount:�� 7 (1.07) ***

#Letter Zcount:�� 1 (0.15)

#

#For Example:

 

# Memory :

# 0x1000:�� W

# 0x1001:�� e

# 0x1002:

# 0x1003:�� h

# 0x1004:�� o

# 0x1005:�� l

# 0x1006:�� d

�� ....

�� ....

# str <=0x1000;

 

# Table :������������������ //we assume0x 7000;

# 0x 7000

# 0x 7001

# 0x 7002

# 0x 7003������������������� //we save int:the numberof 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 aboveis at the end of this notes.

 

 

 

 

histo:

������� ## Register Usage

������� #

������� # Call: $a0String to analyze.

������� #���������� $a1Address 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:

����������� .align2

����������� .globlhisto

����������� .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/ccount: %/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: $a0String to analyze.

������� #������ $a1Address 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