Catalog data: Prereq.: CS 151 or MATH 471. Concepts of assembler language, machine language, macro-instructions, subroutines, program checkout, interrupt structure of assemblers and use of operating system. No credit given to students with credit for MATH 472. [c]
Prerequisites: CS 151 or MATH 471.
Description: This course is an introduction to computer architecture at the assembly language level. The course is based on the MIPS processor, a simple clean RISC processor whose architecture is easy to learn and understand. The course covers binary representation, elements of machine organization, machine language, MIPS assembly language programming, subroutines, interrupts, and basics of operating systems.
Class Participation: Active participation in class is expected of all students. Regular attendance is also expected. If you must miss a test, try to inform the instructor of this in advance.
Honesty policy: It is expected that all students will conduct themselves in an honest manner (see the CCSU Student handbook), and NEVER claim work which is not their own. Violating this policy will result in a substantial grade penalty, and may lead to expulsion from the University. However, students are allowed to discuss projects with others and receive debugging help from others.
Programming: This course teaches assembly programming on a simulator (called SPIM). This is a MIPS machine simulator available as a free software for Unix, DOS, and Windows. There will be 5 programming assignments requiring the use of the SPIM simulator.
Tests: There will be two midterm exams and a final. They will include questions from the textbook, questions from the lectures, and questions from the assignments.
Required textbook: John Waldron, Introduction to RISC Assembly Language Programming, Addison-Wesley, 1999, ISBN 0-201-39828-1.
Required software: SPIM simulator: A free software simulator for running MIPS R2000 assembly language programs available for Unix, DOS, and Windows.
WEB resources:
Grading:Author's web page of Introduction to RISC Assembly Language Programming: Example programs, lecture slides and other resources Publisher's Web page of Introduction to RISC Assembly Language Programming, Addison-Wesley. SPIM simulator: A free software simulator for running MIPS R2000 assembly language programs available for Unix, DOS, and Windows. Documentation for the Windows interface to SPIM: postscript or Adobe PDF file. Assemblers, Linkers, and the SPIM Simulator (Adobe PDF file): Appendix A of Hennessy & Patterson, Computer Organization and Design: The Hardware/Software Interface, Second Edition, Morgan Kaufmann Publishers, Inc., 1997. VAX instruction set (Adobe PDF file) MIPS Web Site Ghostscript, Ghostview and GSview Postscript to PDF Converter
Grading will be based on three tests (two midterms and a final), 2 assignments
and 4 programming projects (see the schedule below for the corresponding
point grades). The letter grades will be calculated according to the following
table:
| A | A- | B+ | B | B- | C+ | C | C- | D+ | D | D- | F |
| 95-100 | 90-94 | 87-89 | 84-86 | 80-83 | 77-79 | 74-76 | 70-73 | 67-69 | 64-66 | 60-63 | 0-59 |
Tentative schedule of classes, assignments and tests:
.text
.globl __start
__start:
la $a0, str
li $v0, 4
syscall
li $v0, 10
syscall
.data
str: .asciiz "hello world\n"
.text
.globl __start
__start: li $v0, 4
la $a0, Ask
syscall
# Print a prompt
li $v0, 5
syscall
# read an integer
# add $s0, $v0, $v0
# $s0 = $v0 + $v0 (an overflow may occur here)
addu $s0, $v0,
$v0 # $s0 = $v0 + $v0 (no overflow)
li $v0, 4
la $a0, Result
syscall
add $a0, $0, $s0
# $a0 = $s0
li $v0, 1
# Print $a0
syscall
li $v0, 4
la $a0, nl
syscall
# Print new line
j __start # Jump to __start (press Ctrl-C for exit)
.data
nl: .asciiz "\n"
Ask: .asciiz "\nEnter an integer number:
"
Result: .asciiz "This number multiplied by 2 is "
1.1. Example run (explain the results)
Enter an integer number: 2
This number multiplied by 2 is 4
Enter an integer number: 1073741823
This number multiplied by 2 is 2147483646
Enter an integer number: 1073741824
This number multiplied by 2 is -2147483648 (wrong result or overflow)
.text
.globl __start
__start: li $v0, 4
la $a0, Ask
syscall
li $v0, 6
syscall
# read a floating point number
li $v0, 4
la $a0, Float
syscall
mov.s $f12, $f0
# move the content of $f0 to $f12
li $v0, 2
# print a floating point number
syscall
li $v0, 4
la $a0, nl
syscall
li $v0, 4
la $a0, Integer
syscall
s.s $f0, Num
# Num = $f0
lw $a0, Num
# $a0 = Num
li $v0, 1
# print the number as integer
syscall
li $v0, 4
la $a0, nl
syscall
j __start # jump to __start (Press Ctrl-C for exit)
.data
Num: .word 0
Ask: .asciiz "\nEnter a floating point
number: "
Float: .asciiz "Floating point: "
Integer: .asciiz "Integer: "
nl: .asciiz "\n"
2.2. Example run (explain the results)
Enter a floating point number: 0
Foating point: 0.000000
Integer: 0
Enter a floating point number: -0
Foating point: 0.000000
Integer: -2147483648
Enter a floating point number: 1
Foating point: 1.000000
Integer: 1065353216
Enter a floating point number: -1
Foating point: -1.000000
Integer: -1082130432
Enter a floating point number: 1e38
Foating point: 99999996802856925000000000000000000000.000000
Integer: 2123789977
Enter a floating point number: 1e39
Foating point: 1.#INF00
Integer: 2139095040
Enter a floating point number: 1e-45
Foating point: 0.000000
Integer: 1
Enter a floating point number: 1e-46
Foating point: 0.000000
Integer: 0
# Input a number into a four-bytes word and print the individual
bytes
# The program runs into an infinite loop. Press Ctrl-C for exit.
.text
.globl __start
__start: li $v0, 4
la $a0, Prompt
syscall
# Print a promt
li $v0, 5
syscall
# Read an integer into word A
sw $v0, A
lbu $a0, A
li $v0, 1
syscall
# Print the first byte of A
li $v0, 4
la $a0, B0
syscall
# Print the string " * 256^0 + "
lbu $a0, B
li $v0, 1
syscall
# Print the second byte of A
li $v0, 4
la $a0, B1
syscall
# Print the string " * 256^1 + "
lbu $a0, C
li $v0, 1
syscall
# Print the third byte of A
li $v0, 4
la $a0, B2
syscall
# Print the string " * 256^2 + "
lbu $a0, D
li $v0, 1
syscall
# Print the fourth byte of A
li $v0, 4
la $a0, B3
syscall
# Print the string " * 256^3\n"
j __start # jump to __start
.data
A: .byte 0
B: .byte 0
C: .byte 0
D: .byte 0
B0: .asciiz " * 256^0 + "
B1: .asciiz " * 256^1 + "
B2: .asciiz " * 256^2 + "
B3: .asciiz " * 256^3\n"
Prompt: .asciiz "Enter a number: "
1.2. Example run
Enter a number: 255
255 * 256^0 + 0 * 256^1 + 0 * 256^2 + 0 * 256^3
Enter a number: 256
0 * 256^0 + 1 * 256^1 + 0 * 256^2 + 0 * 256^3
Enter a number: 65535
255 * 256^0 + 255 * 256^1 + 0 * 256^2 + 0 * 256^3
Enter a number: 65536
0 * 256^0 + 0 * 256^1 + 1 * 256^2 + 0 * 256^3
Enter a number: -1
255 * 256^0 + 255 * 256^1 + 255 * 256^2 + 255 * 256^3
Enter a number: 2147483647
255 * 256^0 + 255 * 256^1 + 255 * 256^2 + 127 * 256^3
Enter a number: 2147483648
0 * 256^0 + 0 * 256^1 + 0 * 256^2 + 128 * 256^3
Enter a number: -2147483648
0 * 256^0 + 0 * 256^1 + 0 * 256^2 + 128 * 256^3
# Input A,B,C,D and print the value of A*256^0+B*256^1+C*256^2+D*256^3
# The program runs into an infinite loop. Press Ctrl-C for exit.
.text
.globl __start
__start: li $v0, 4
la $a0, LA
syscall
li $v0, 5
# read A
syscall
sb $v0, A
# store A in byte 0
li $v0, 4
la $a0, LB
syscall
li $v0, 5
# read B
syscall
sb $v0, B
# store B in byte 1
li $v0, 4
la $a0, LC
syscall
li $v0, 5
# read C
syscall
sb $v0, C
# store C in byte 2
li $v0, 4
la $a0, LD
syscall
li $v0, 5
# read D
syscall
sb $v0, D
# store D in byte 3
li $v0, 4
la $a0, Result
# Print the string "A * 256^0 + B * 256^1 + C * 256^2 + D * 256^3 = "
syscall
lw $a0, A
# print the word: byte0, byte1, byte2, byte3
li $v0, 1
syscall
li $v0, 4
la $a0, nl
syscall
j __start # jump to __start
.data
A: .byte 0
B: .byte 0
C: .byte 0
D: .byte 0
LA: .asciiz "A="
LB: .asciiz "B="
LC: .asciiz "C="
LD: .asciiz "D="
Result: .asciiz "A * 256^0 + B * 256^1 + C * 256^2 + D *
256^3 = "
nl: .asciiz "\n"
2.2. Example run
A=255
B=255
C=255
D=127
A * 256^0 + B * 256^1 + C * 256^2 + D * 256^3 = 2147483647
A=255
B=255
C=255
D=128
A * 256^0 + B * 256^1 + C * 256^2 + D * 256^3 = -2130706433
A=0
B=0
C=0
D=256
A * 256^0 + B * 256^1 + C * 256^2 + D * 256^3 = 0
A=0
B=0
C=0
D=255
A * 256^0 + B * 256^1 + C * 256^2 + D * 256^3 = -16777216
## temp.a ask user for temperature in Celsius,
## convert to Fahrenheit, print the result.
##
## v0 - reads in celsius
## t0 - holds Fahrenheit result
## a0 - points to output strings
##
#################################################
#
text segment
#
#################################################
.text
.globl __start
__start:
la $a0,prompt
# print prompt on terminal
li $v0,4
syscall
li $v0,5
# syscall 5 reads an integer
syscall
# We use here two pseudo-instructions - mul and div
mul $t0,$v0,9
# to convert,multiply by 9,
div $t0,$t0,5
# divide by 5,then
add $t0,$t0,32
# add 32
la $a0,ans1
# print string before result
li $v0,4
syscall
move $a0,$t0
# print result
li $v0,1
syscall
la $a0,endl
# system call to print
li $v0,4
# out a newline
syscall
li $v0,10
syscall
# au revoir...
#################################################
#
data segment
#
#################################################
.data
prompt: .asciiz "Enter temperature (Celsius): "
ans1: .asciiz "The temperature in Fahrenheit is "
endl: .asciiz "\n"
# Convert a 3-digit decimal string into an integer
.text
.globl __start
__start: la $t0, Num
lb $v0, 2($t0)
# load the ascii code of digit 0
addi $v0, $v0,
-48 # get the value of digit 0
add $v1, $0, $v0
# add to the total
lb $v0, 1($t0)
# load the ascii code of digit 1
addi $v0, $v0,
-48 # get the value of digit 1
mul $v0, $v0,
10 # multiply by 10
add $v1, $v1,
$v0 # add to the total
lb $v0, 0($t0)
# load the ascii code of digit 2
addi $v0, $v0,
-48 # get the value of digit 1
mul $v0, $v0,
100 # multiply by 10
add $v1, $v1,
$v0 # add to the total
sw $v1, Value # store the total
.data
Num: .asciiz "256"
Value: .word 0
Random number generator
# Random number generator
# seed:=(x*seed+y) mod z
# Prints an infinite sequence of pseudo-random numbers (press
Ctrl-C for exit)
.text
.globl __start
__start: lw $t0, x
# $t0 = x
lw $t1, seed
mul $t0, $t0,
$t1 # $t0 = x*seed
lw $t1, y
add $t0, $t0,
$t1 # $t0 = x*seed+y
lw $t1, z
div $t0, $t1
# hi = (x*seed+y) mod z
mfhi $a0
# $a0 = hi
sw $a0, seed
# seed = $a0
li $v0, 1
syscall
# print seed
li $v0, 4
la $a0, nl
syscall
# print new line
b __start # goto to __start (set a breakpoint here)
.data
x: .word 31
# an arbitrary constant
y: .word 23
# an arbitrary constant
z: .word 10000
# the range of random rumbers [0,9999]
seed: .word 0
# the initial seed is 0
nl: .asciiz "\n"
# Check for leap year
# In Gregorian Calendar: "A year is a leap year if it is
divisible by 4 with
# the exception of century years that are not divisible by
400"
# That is: if (Year mod 4 <> 0) then Ordinary
# else
if (Year mod 100 = 0) and (Year mod 400 <> 0) then Ordinary
# else
Leap
.text
.globl __start
__start: li $v0, 4
la $a0, Prompt
syscall
# Print a prompt
li $v0, 5
syscall
# Read an integer
sw $v0, Year
# and store it in Year
# if (Year mod 4 <> 0) then go to Ordinary
lw $t0, Year
li $t1, 4
div $t0, $t1
# hi = year mod 4
mfhi $t1
# $t1 = hi
bne $t1, $0, Ordinary
# if $t1 <> 0 go to Ordinary
# if (Year mod 100 = 0) and (year mod 400 <> 0) then go to Ordinary
# if (Year mod 100 <> 0) then go to Leap
li $t1, 100
div $t0, $t1
# hi = year mod 100
mfhi $t1
# $t1 = hi
bne $t1, $0, Leap
# if $t1 <> 0 go to Leap
# if (Year mod 400 <> 0) then go to Ordinary
li $t1, 400
div $t0,
$t1 # hi =
year mod 400
mfhi $t1
# $t1 = hi
bne $t1,
$0, Ordinary # if $t1 <> 0 go to Ordinary
Leap: lw $a0, Year
# Leap year
li $v0,
1
syscall
# Print Year
li $v0,
4
la $a0,
LeapMess
syscall
# Print " is a leap year\n"
b End
# go to End
Ordinary: lw $a0, Year
# Ordinary year
li $v0,
1
syscall
# Print Year
li $v0,
4
la $a0,
OrdMess
syscall
# Print " is an ordinary year\n"
End: b __start # go to __start (read another year)
.data
Year: .word 0
Prompt: .asciiz "Enter year: "
LeapMess: .asciiz " is a leap year\n"
OrdMess: .asciiz " is an ordinary year\n"
.text
.globl __start
__start: li $v0, 4
la $a0, First
syscall
# Ask for the first integer
li $v0, 5
syscall
# Read an integer
add $t0, $0, $v0
# and store it in $t0
li $v0, 4
la $a0, Second
syscall
# Ask for the second integer
li $v0, 5
syscall
# Read an integer
add $t1, $0, $v0
# and store it in $t1
# Include here one of the following two versions
# Version 1: based on integer division
loop: div $t0, $t1
mfhi $t2
# $t2 = $t0 mod $t1
add $t0, $0, $t1
# $t0 = $t1
add $t1, $0, $t2
# $t1 = $t2
bne $t1, $0, loop
# Version 2: based on subtract
#loop: beq $t0, $t1, exit
# if the numbers are equal then exit
# bgt $t0, $t1,
skip # subtract the smaller from the bigger
# sub $t1, $t1,
$t0 # and replace the bigger with the result
# b loop
# then continue
#skip: sub $t0, $t0, $t1
# b loop
# end of inclusion
exit: li $v0, 4
la $a0, Ans
syscall
# Print "The GCD is: "
add $a0, $0, $t0
li $v0, 1
syscall
# Print GCD
li $v0, 4
la $a0, nl
syscall
# Print new line
b __start # Go to __start (Press Ctrl-C for exit)
.data
First: .asciiz "Calculating GCD of two integers.\nEnter
first integer: "
Second: .asciiz "Enter second integer: "
Ans: .asciiz "Their GCD is: "
nl: .asciiz "\n\n"
.text
.globl __start
__start:
# execution starts here
la $t2,str
# t2 points to the string
li $t1,0
# t1 holds the count
nextCh: lb $t0,($t2) # get a byte from string
beqz $t0,strEnd # zero
means end of string
add $t1,$t1,1
# increment count
add $t2,1
# move pointer one character
j nextCh
# go round the loop again
strEnd: la $a0,ans # system call to
print
li $v0,4
# out a message
syscall
move $a0,$t1
# system call to print
li $v0,1
# out the length worked out
syscall
la $a0,endl
# system call to print
li $v0,4
# out a newline
syscall
li $v0,10
syscall
# au revoir...
#################################################
#
data segment
#
#################################################
.data
str: .asciiz "hello world"
ans: .asciiz "Length is "
endl: .asciiz "\n"
# Generate two random numbers as X and Y coordinates of a
point:
# ($f1, $f2) in [-1,1] X [-1,1]
# Then count the points which fall within the unit circle
($f1^2 + $f2^2 <= 1).
# Pi is the quotient of this number and the total number
of points generated
# multiplied by 4.
.text
.globl __start
__start:
#--- Initialize counters --------------------------------------------------
lw $s0, n
# n is the number of points generated
li $s1, 0
# $s1 counts the points inside the unit circle
loop:
#--- Generate a random value (float in [-1,1]) and store it in $f1 --------
lw $t0, x
# $t0 = x
lw $t1, seed
mul $t0, $t0,
$t1 # $t0 = x*seed
lw $t1, y
addu $t0, $t0,
$t1 # $t0 = x*seed+y
lw $t1, z
div $t0, $t1
# hi = (x*seed+y) mod z
mfhi $t1
# $t1 = hi
sw $t1, seed
# store the new value in seed
l.s $f1, seed
cvt.s.w $f1, $f1
# covert integer into float, $f1 = seed
l.s $f0, z
cvt.s.w $f0, $f0
# convert integer to float, $f0=z
div.s $f1, $f1,
$f0 # normalize $f1, i.e. $f1 in [0,1]
add.s $f1, $f1,
$f1 # $f1 = $f1*2
l.s $f0, one
# $f0 = 1.0
sub.s $f1, $f1,
$f0 # $f1 = $f1-1, $f1 in [-1,1]
#---------------------------------------------------------------------------
mov.s $f2, $f3
# Put the previous value ($f3) in $f2
mov.s $f3, $f1
# Store the current one ($f1) in $f3
#--- $f1 = $f1^2 + $f2^2 ---------------------------------------------------
mul.s $f1, $f1,
$f1 # $f1=$f1^2
mul.s $f2, $f2,
$f2 # $f2=$f2^2
add.s $f1, $f1,
$f2 # $f1=$f1+$f2
#--- $f1^2 + $f2^2 <= 1 (compare floating point values using integers) -----
s.s $f1, temp
lw $t2, temp
# $t2 (integer) = $f1 (float)
lw $t1, one
# $t1 (integer) = 1.0 (float)
slt $t0, $t1, $t2
bne $t0, $0, skip
addi $s1, $s1,
1
skip: addi $s0, $s0, -1
bne $s0, $0, loop
# calculate PI = (# of points inside circle) * 4 / n ----------------------
add $s1, $s1, $s1
# $s1 = $s1*4
add $s1, $s1,
$s1
sw $s1, temp
l.s $f12, temp
cvt.s.w $f12,
$f12
l.s $f0, n
cvt.s.w $f0, $f0
div.s $f12, $f12,
$f0
li $v0, 2
syscall
# Print the value of Pi
li $v0, 4
la $a0, bye
# Print the end message
syscall
li $v0, 5
syscall
# wait for Enter
li $v0, 10
syscall
# end of program
#--------------------------------------------------------------------------
.data
x: .word 311
y: .word 171
z: .word 65536
n: .word 10000
one: .float 1.0
seed: .word 79
temp: .word 0
bye: .asciiz "\nPress enter to exit..."
# Read and print a sequence of numbers by using arrays.
# Questions (memory organization):
# 1. What hapens if we enter more than 10 numbers (the array
has 10 elements)
# 2. What about moving the array at the end of the data segment?
.text
.globl __start
__start: la $s0, array # set
$s0 to point array[0]
li $s1, 0
# $s1 = 0 (for counting the array elements)
loop1: li $v0, 4
la $a0, prompt
syscall
# Print the prompt
li $v0, 5
syscall
# Read an integer in $v0
lw $t0, endmark
beq $v0, $t0,
exit # if $v0 = endmark then exit loop
sw $v0, 0($s0)
# store $v0 into the current element
addi $s0, $s0,
4 # move to the next element
addi $s1, $s1,
1 # increment the counter
b loop1
exit: li $v0, 4
la $a0, res
syscall
add $a0, $0, $s1
li $v0, 1
syscall
# Print the number of elements entered
li $v0, 4
la $a0, el
syscall
la $s0, array # set $s0 to point to array[0]
loop2: lw $a0, 0($s0)
# $a0 = current element
li $v0, 1
syscall
# Print $a0
li $v0, 4
la $a0, nl
syscall
add $s0, $s0,
4 # move to the next element
addi $s1, $s1,
-1 # decrement element counter
bne $s1, $0, loop2
li $v0, 4
la $a0, bye
# Print the end message
syscall
li $v0, 5
syscall
# wait for Enter
li $v0, 10
syscall
# end of program
.data
array: .word 0,0,0,0,0,0,0,0,0,0
prompt: .asciiz "Enter an integer (-999 for exit): "
endmark: .word -999
res: .asciiz "You have entered "
el: .asciiz " numbers:\n"
bye: .asciiz "Press enter to exit..."
nl: .asciiz "\n"
# array: .word 0,0,0,0,0,0,0,0,0,0
# Read an array of numbers and find the minimal and maximal elements
.text
.globl __start
__start: la $s0, array
# set $s0 to point array[0]
li $s1,
0
# $s1 = 0 (for counting the array elements)
loop1: li $v0, 4
la $a0,
ask
syscall
# Ask for a number
li $v0,
5
syscall
# Read an integer in $v0
lw $t0,
endmark
beq $v0,
$t0, exit # if $v0 = endmark then exit loop
sw $v0,
0($s0) # store $v0 into the current
element of the array
addi $s0,
$s0, 4 # move to the next element
addi $s1,
$s1, 1 # increment the counter
b loop1
exit: li $v0, 4
la $a0, res
# Print "You have entered "
syscall
add $a0, $0, $s1
li $v0, 1
syscall
# Print the number of elements entered
li $v0, 4
la $a0, numb
# Print " numbers.\n"
syscall
la $s0, array
# set $s0 to point to array[0]
lw $t0, 0($s0)
# initialize min ($t0) to array[0]
lw $t1, 0($s0)
# initialize max ($t1) to array[0]
loop2: lw $t3, 0($s0) # $t3 = current element
bge $t3, $t0, notmin
# skip if current element >= min
add $t0, $0, $t3
# update min ($t0)
notmin: ble $t3, $t1, notmax # skip if current
element <= max
add $t1, $0, $t3
# update max ($t1)
notmax: add $s0, $s0, 4
# move to the next element
addi $s1, $s1,
-1 # decrement element counter
bne $s1, $0, loop2
li $v0, 4
la $a0, min
# Print "Minimal number = "
syscall
add $a0, $0, $t0
li $v0, 1
# Print the value of min
syscall
li $v0, 4
la $a0, nl
syscall
li $v0, 4
la $a0, max
# Print "Maximal number = "
syscall
add $a0, $0, $t1
li $v0, 1
# Print the value of max
syscall
li $v0, 4
la $a0, nl
syscall
li $v0, 4
la $a0, bye
# Print the end message
syscall
li $v0, 5
syscall
# wait for Enter
li $v0, 10
syscall
# end of program
.data
ask: .asciiz "Enter an integer (-999 for
exit): "
endmark: .word -999
res: .asciiz "You have entered "
numb: .asciiz " numbers.\n"
min: .asciiz "Minimal number = "
max: .asciiz "Maximal number = "
bye: .asciiz "Press enter to exit..."
nl: .asciiz "\n"
array: .word 0
# the array starts here
# Bubble sort
# Repeatedly swapping pairs of wrongly ordered elements until
# all pairs are correctly ordered.
.text
.globl __start
__start: la $s0, array
# set $s0 to point array[0]
li $s1, 0
# $s1 = 0 (for counting the array elements)
# Read in the array elements
loop1: li $v0, 4
la $a0, ask
syscall
# Ask for a number
li $v0, 5
syscall
# Read an integer in $v0
lw $t0, endmark
beq $v0, $t0,
loop2 # if $v0 = endmark then exit loop
sw $v0, 0($s0)
# store $v0 into the current element of the array
addi $s0, $s0,
4 # move to the next element
addi $s1, $s1,
1 # increment the counter
b loop1
# Sort the array by using the bubble sort algorithm
loop2: la $s0, array
# set $s0 to point to array[0]
add $s2, $0, $s1
# $s2 = $s1 (the number of elements)
add $s2, $s2, -1
# number of swaps = number of elements - 1
add $t3, $0, $0
# number of swaps ($t3) = 0
loop3: lw $t0, 0($s0)
# $t0 = current element
lw $t1, 4($s0)
# $t1 = next element
slt $t2, $t1, $t0
# if $t1 < $t0 then $t2 = 1
beq $t2, $0, skip
# if $t2 = 0 the go to skip
sw $t0, 4($s0)
# swap the current element and
sw $t1, 0($s0)
# the next element
addi $t3, $t3, 1
# increment $t3 (number of swaps)
skip: add $s0, $s0, 4
# move to the next element
addi $s2, $s2, -1
# decrement the element counter
bgt $s2, $0, loop3
# if $s2 > 0 then go to loop3
bne $t3, $0, loop2 # if number of swaps > 0 then go to loop2
# Print the sorted array
li $v0, 4
la $a0, sorted
# Print "Sorted: "
syscall
la $s0, array
loop4: lw $a0, 0($s0)
li $v0, 1
syscall
li $v0, 4
la $a0, nl
syscall
add $s0, $s0,
4
addi $s1, $s1,
-1
bne $s1, $0, loop4
li $v0, 4
la $a0, bye
# Print the end message
syscall
li $v0, 5
syscall
# wait for Enter
li $v0, 10
syscall
# end of program
.data
ask: .asciiz "Enter an integer (-999 for
exit): "
endmark: .word -999
sorted: .asciiz "Sorted:\n"
bye: .asciiz "Press enter to exit..."
nl: .asciiz "\n"
array: .word 0
# the array starts here
#################################################
#
text segment
#
#################################################
.text
.globl __start
__start:
li $t1,0
# $t1 will be the array index
li $t2,0
# $t2 will be the counter
lb $t3,char
# and $t3 will hold the char
loop: lb $t0,str($t1) # fetch next char
beqz $t0,strEnd # if
it's a null, exit loop
bne $t0,$t3,con # not
null; same as char?
add $t2,$t2,1
# yes,increment counter
con: add $t1,$t1,1 # increase index
j loop
# and continue
strEnd:
la $a0,ans
# system call to print
li $v0,4
# out a message
syscall
move $a0,$t2
# system call to print
li $v0,1
# out the count worked out
syscall
la $a0,endl
# system call to print
li $v0,4
# out a newline
syscall
li $v0,10
syscall
# au revoir...
#################################################
#
data segment
#
#################################################
.data
str: .asciiz "abceebceebeebbacacb"
char: .asciiz "e"
ans: .asciiz "Count is "
endl: .asciiz "\n"
##
## end of file count.a
.text
.globl __start
__start: li $v0, 4
la $a0, ask
# Print "Type a character string: "
syscall
la $a0, buffer
# $a0 holds the address of the read buffer
lw $a1, maxlen
# Max number of chars (including the end of string char)
li $v0, 8
# Load the service number
syscall
# Call the operating system
# Copy the buffer into str and replace lower case letters with upper case letters
li $t2, 97
# the ASCII code of "a"
li $t3, 122
# the ASCII code of "z"
li $t0, 0
# $t0 is the index
loop: lb $t1, buffer($t0) # fetch a char
from the buffer
blt $t1, $t2,
skip # the char is before "a", skip it
bgt $t1, $t3,
skip # the char is after "z", skip it
addi $t1, $t1,
-32 # convert to upper case
skip: sb $t1, str($t0)
# and store it into str
addi $t0, $t0,
1 # increment index
bne $t1, $0, loop
# if $t1 <> "end of string" then goto loop
li $v0, 4
la $a0, str
# Print str
syscall
li $v0, 4
la $a0, bye
# Print the end message
syscall
li $v0, 5
syscall
# wait for Enter
li $v0, 10
syscall
# end of program
.data
ask: .asciiz "Type a character string (<31
chars long): "
bye: .asciiz "Press enter to exit..."
nl: .asciiz "\n"
maxlen: .word 31
buffer: .space 31
# allocates 31 bytes of memory in the data segment
str: .space 31
.text
.globl __start
__start:
la $a0,prompt
# print prompt on terminal
li $v0,4
syscall
li $v0,5
# syscall 5 reads an integer
syscall
move $t2,$v0
# $t2 holds hex number
la $a0,ans1
# print string before result
li $v0,4
syscall
li $t4, 4 # for printing blank after 4 digits
li $t0, 32
# 32 bits in word
la $t3,result
# answer string set up here
loop: rol $t2,$t2,1 # start with leftmost
digit
and $t1,$t2,1
# mask one binary digit
# print blank after 4 digits
div $t0, $t4
mfhi $t5
bnez $t5, skip
la $a0,blank
# print blank
li $v0,4
syscall
skip: move $a0, $t1 # print digit
as integer
li $v0, 1
syscall
# store digit in string
add $t1,$t1,48
# ASCII '0' is 48
sb $t1,($t3)
# save in string
add $t3,$t3,1
# advance destination pointer
add $t0,$t0,-1
# decrement counter
bnez $t0,loop
# and continue if counter>0
# print result as a string on terminal
la $a0,binstr
li $v0,4
syscall
la $a0,result
li $v0,4
syscall
j __start
#--------------------------------------------------
.data
result: .space 32
.byte 0
prompt: .asciiz "\nEnter decimal number: "
ans1: .asciiz "Binary is: "
binstr: .asciiz "\nBinary string: "
blank: .asciiz " "
.text
.globl __start
__start:
la $a0,prompt
# print prompt on terminal
li $v0,4
syscall
li $v0,5
# syscall 5 reads an integer
syscall
move $t2,$v0
# $t2 holds hex number
la $a0,ans1
# print string before result
li $v0,4
syscall
li $t0,8
# eight hex digits in word
la $t3,result
# answer string set up here
loop: rol $t2,$t2,4 # start with leftmost
digit
and $t1,$t2,0xf # mask
one digit
ble $t1,9,print # check
if 0 to 9
add $t1,$t1,7
# 7 chars between '9' and 'A'
print: add $t1,$t1,48 # ASCII '0' is 48
sb $t1,($t3)
# save in string
add $t3,$t3,1
# advance destination pointer
add $t0,$t0,-1
# decrement counter
bnez $t0,loop
# and continue if counter>0
la $a0,result
# print result on terminal
li $v0,4
syscall
li $v0,10
syscall
# au revoir...
#################################################
#
data segment
#
#################################################
.data
result: .space 8
.asciiz "\n"
prompt: .asciiz "Enter decimal number: "
ans1: .asciiz "Hexadecimal is "
The Program
# Implementing sets (set union, and set membership) by using
logical operations
# Questions:
# 1. How are the elements sorted?
# 2. Why is each element printed just once?
# 3. What happens when we enter a number > 31
?
.text
.globl __start
__start: li $t1, 1
li $s0, 0
# initialize the set to {}
loop1: li $v0, 4
la $a0, prompt
# Print a prompt
syscall
li $v0, 5
syscall
# Read a number in $v0
bltz $v0, exit
sllv $s1, $t1,
$v0 # set the $v0-th bit in $s1 to 1, one element set - {$v0}
or $s0, $s0, $s1
# set unition, $s0 = $s0 U {$v0}
b loop1
# Print the set $s0
exit: li $v0, 4
la $a0, result
# Print "You have entered:\n"
syscall
li $t3, 0
# clear the counter
li $t4, 32
# the last value
loop2: and $t2, $s0, $t1 # check the $t1-the
bit in $s0 ($t1 in $s0 ?)
beq $t2, $0, skip
# if $t1-th bit is zero then go to skip
li $v0, 1
add $a0, $0, $t3
syscall
# Print the counter
li $v0, 4
la $a0, nl
# Print new line
syscall
skip: sll $t1, $t1, 1
# shift the 1 one bit left
addi $t3, $t3,
1 # increment the counter
bne $t3, $t4,
loop2
li $v0, 4
la $a0, bye
# Print the end message
syscall
li $v0, 5
syscall
# wait for Enter
li $v0, 10
syscall
# end of program
.data
prompt: .asciiz "Enter a number in [0,31] (<0 for exit):
"
result: .asciiz "You have entered:\n"
bye: .asciiz "Press enter to exit..."
nl: .asciiz "\n"
Example run
Enter a number in [0,31] (<0 for exit): 0
Enter a number in [0,31] (<0 for exit): 5
Enter a number in [0,31] (<0 for exit): 1
Enter a number in [0,31] (<0 for exit): 4
Enter a number in [0,31] (<0 for exit): 1
Enter a number in [0,31] (<0 for exit): 0
Enter a number in [0,31] (<0 for exit): -1
You have entered:
0
1
4
5
Press enter to exit...
Enter a number in [0,31] (<0 for exit): 45
Enter a number in [0,31] (<0 for exit): 39
Enter a number in [0,31] (<0 for exit): 32
Enter a number in [0,31] (<0 for exit): -1
You have entered:
0
7
13
Press enter to exit...
# Prime numbers: The sieve of Eratosthenes.
# Print the primes in the interval [2,N]:
# S = {2,3,4,...,N}
# P = 2;
# for P = 2 to N do begin
# if P in S then begin
# I:=2;
# while P*I <= N do begin
# S = S \ {P*I}
# I = I+1
# end
# end
# end
# print S
.text
.globl __start
__start: li $s0 0xFFFFFFFF
# S($s0) = {0,1,2,3,4,...,31}
li $t0, 2
# P($t0) = 2
li $t2, 31
# N($t2) = 31
li $t1, 1
# the moving "1"
loop: sllv $t3, $t1, $t0
# set the $t0-th bit of $t3 to 1
and $t3, $s0,
$t3 # P in S ?
beq $t3, $0, skip
# if no, go to skip
li $t4, 2
# I($t4) = 2
loop1: mul $t5, $t0, $t4
# $t5 = P*I
bgt $t5, $t2,
skip # if P*I > N then
go to skip
sllv $t3, $t1,
$t5 # set the (P*I)-th
bit of $t3 to 1
nor $t3, $t3,
$0 # switch
the bits in $t3 (1 <-> 0)
and $s0, $s0,
$t3 # S = S \{P*I}
(clear the (P*I)-th bit of $s0)
add $t4, $t4,
1 # I
= I+1
b loop1
skip: add $t0, $t0, 1
# P = P + 1
ble $t0, $t2,
loop # if P <= N then
go to loop
li $v0, 4
la $a0, result
# Print "The prime numbers in [0,31] are:\n"
syscall
# Print the set S($s0), starting from 2
li $t0, 2
li $t1, 4
loop2: and $t3, $s0, $t1
# $t1 in $s0 ?
beq $t3, $0, skip2
# if no, go to skip2
li $v0, 1
add $a0, $0, $t0
syscall
# Print $t1
li $v0, 4
la $a0, nl
syscall
# Print new line
skip2: sll $t1, $t1, 1
# move the "1" in $t1 one bit to the left
addi $t0, $t0,
1 # increment
$t0
ble $t0, $t2,
loop2 # if $t0 <= 31 then
go to loop2
li $v0, 4
la $a0, bye
# Print the end message
syscall
li $v0, 5
syscall
# wait for Enter
li $v0, 10
syscall
# end of program
.data
result: .asciiz "The prime numbers in [0,31] are:\n"
bye: .asciiz "Press enter to exit..."
nl: .asciiz "\n"
Reversing a character string
## reverse.a - reverse the character
## string "str".
##
## t1 - points to the string
## t0 - holds each byte from string in turn
##
#################################################
# text segment
#
#################################################
.text
.globl __start
__start:
la $t1,str
# a0 points to the string
nextCh: lb $t0,($t1) # get a byte from
string
beqz $t0,strEnd
# zero means end of string
sub $sp,$sp,4
# adjust stack pointer
sw $t0,($sp)
# PUSH the t0 register
add $t1,1
# move pointer one character
j nextCh
# go round the loop again
strEnd: la $t1,str # a0 points
to the string
store: lb $t0,($t1) # get a byte
from string
beqz $t0,done
# zero means end of string
lw $t0,($sp)
# POP a value from the stack
add $sp,$sp,4
# and adjust the pointer
sb $t0,($t1)
# store in string
add $t1,1
# move pointer one character
j store
done: la $a0,str
# system call to print
li $v0,4
# out a message
syscall
la $a0,endl
# system call to print
li $v0,4
# out a newline
syscall
li $v0,10
syscall
# au revoir...
#################################################
# data segment
#
#################################################
.data
str: .asciiz "hello world"
endl: .asciiz "\n"
Reverse polish calculator (evaluating expressions in postfix notation)
.text
.globl __start
__start: li $v0, 4
la $a0, ask
# Print "Type an expression (single digit numbers only): "
syscall
la $a0, buffer
# $a0 holds the address of the read buffer
lw $a1, maxlen
# Max number of chars (including the end of string char)
li $v0, 8
# Load the service number (read a string)
syscall
# Call the operating system
li $t3, 10
# ASCII 10 (LF) is the last char in the string
lb $t4, timesc
# ASCII "*"
lb $t5, plusc
# ASCII "+"
lb $t6, minusc
# ASCII "-"
lb $t7, overc
# ASCII "/"
loop: lb $t0,0($a0)
# get a byte from the string
beq $t0, $t3,
done # check for end
add $a0, $a0,
1 # move the chars pointer to the next char
blt $t0, 48, op
# ASCII<48 => not a number, possibly op
bgt $t0, 57, op
# ASCII>57 => not a number, possibly op
addi $t0, $t0,
-48 # convert an ASCII digit to a numerical value
sub $sp, $sp,
4 # move the stack pointer
sw $t0, 0($sp)
# PUSH $t0 into the stack
b loop
op: lw $t2, 0($sp)
# PULL $t2 from stack
add $sp, $sp,
4
lw $t1, 0($sp)
# PULL $t1 from stack
add $sp, $sp,
4
beq $t0, $t4,
times
beq $t0, $t5,
plus
beq $t0, $t6,
minus
beq $t0, $t7,
over
b loop
# go round the loop again
times: mul $t0, $t1, $t2
b next
plus: add $t0, $t1, $t2
b next
minus: sub $t0, $t1, $t2
b next
over: div $t0, $t1, $t2
next: sub $sp, $sp, 4 # move
the stack pointer
sw $t0, 0($sp)
# PUSH the result ($t0) into the stack
b loop
done: lw $a0, 0($sp) #
PULL the result from the stack
li $v0, 1
syscall
# Print the result
li $v0, 4
la $a0, bye
# Print the end message
syscall
li $v0, 5
syscall
# wait for Enter
li $v0, 10
syscall
# end of program
.data
ask: .asciiz "Type an expression (single digit
numbers only): "
bye: .asciiz "\nPress enter to exit...\n"
maxlen: .word 31
buffer: .space 31
timesc: .ascii "*"
plusc: .ascii "+"
minusc: .ascii "-"
overc: .ascii "/"
Adding two rational numbers
.text
.globl __start
__start: li $v0, 4
la $a0, Prompt
syscall
li $v0, 5
syscall
# Read an integer in $v0
move $a0, $v0
# and store it in $a0
li $v0, 5
syscall
# Read an integer in $v0
move $a1 $v0
# and store it in $a1
li $v0, 5
syscall
# Read an integer in $v0
move $a2, $v0
# and store it in $a2
li $v0, 5
syscall
# Read an integer in $v0
move $a3, $v0
# and store it in $a3
jal addtwo
move $s0, $a0 # save $a0
li $v0, 4
la $a0, Result
syscall
# Print the result
move $a0, $s0
# restore $a0
li $v0, 1
syscall
# Print $a0
li $v0, 4
la $a0, slash
syscall
move $a0, $a1
li $v0, 1
syscall
# Print $a1
li $v0, 4
la $a0, bye
# Print the end message
syscall
li $v0, 5
syscall
# wait for Enter
li $v0, 10
syscall
# end of program
#------------------------------------------------------------
# Add fractions
#------------------------------------------------------------
# Input: $a0/$a1, $a2/$a3 - two fractions
#------------------------------------------------------------
# Output: $a0/$a1 = $a0/$a1 + $a2/$a3 (in rational numbers)
#------------------------------------------------------------
addtwo: sub $sp, $sp, 4
sw $ra, 0($sp)
mul $t0, $a0, $a3
mul $t1, $a2, $a1
add $t0, $t0, $t1
mul $t1, $a1, $a3
move $a0, $t0
move $a1, $t1
jal gcd
div $a0, $a0, $v0
div $a1, $a1, $v0
lw $ra, 0($sp)
add $sp, $sp, 4
jr $ra
#--------------------------------------------------
# GCD procedure
#--------------------------------------------------
# Input: $a0, $a1 - two integers
#--------------------------------------------------
# Output: $v0 - the GCD of $a0 and $a1
#--------------------------------------------------
gcd: move $t0, $a0
# move the arguments
move $t1, $a1
# to temporary variables
loop: div $t0, $t1
# $t2 = $t0 mod $t1
mfhi $t2
move $t0, $t1
# $t0 = $t1
move $t1, $t2
# $t1 = $t2
bne $t1, $0, loop
move $v0, $t0 # move the return value to $v0
jr $ra # return
#-------------------------------------------------------------------------
.data
Prompt: .asciiz "Enter four integers (A,B,C,D) for A/B and
C/D:\n"
Result: .asciiz "A/B + C/D = "
slash: .asciiz "/"
bye: .asciiz "\nPress enter to exit..."
# main ()
# {
# printf ( fact (10);
# }
.text
.globl __start
__start: li $a0, 10 #
Put argument (10) in $a0
&nbs