Homework 09: MIPS32
assembly in SPIM
This homework is a continuation of the work you did in Lab
09 using spim
to execute MIPS32 programs that you
write in its assembly language. Follow the instructions there for
getting the spim
and running the code.
Here I have four exercises, three building from ideas from
Lecture 09-2 and Lecture 10-1,
namely:
- Working with an array of integers held in memory using
LW
.
- Working with a linked list of data pairs held in memory using
LW
and SW
at an offset.
- Working with the underlying bits held in a register using
SLL
, SRL
, and ANDI
.
I’ve also included several sample programs from these lectures for
your reference. In some cases it’ll be best to solve an exercise by
using one of these samples as a start.
Here again are some resources you can reference to on MIPS and
SPIM:
• the SPIM
simulator
• SPIM’s
MIPS information links
• the
MIPS32 programmer’s guide
For today, you might most benefit by referencing these:
• the
MIPS32 quick reference
• this
SPIM system call reference
These two, and the instructions and examples below, ought to be enough
for you get this work done.
Here also is a summary of the MIPS32 instruction set we’ve learned: *
ADD $Rdst, $Rsrc1, $Rsrc2
: sum two registers, placing
result in a third * ADDI $Rdst, $Rsrc, constant
: sum a
register with a constant * SUB $Rdst, $Rsrc1, $Rsrc2
:
subtract two registers, placing result in a third *
AND $Rdst, $Rsrc1, $Rsrc2
: compute the bitwise AND of two
registers, placing result in a third *
ANDI $Rdst, $Rsrc, constant
: compute the bitwise AND of a
register with a constant * SLL $Rdst, $Rsrc, positions
:
shift a register’s bits left some number of positions, storing the
result in another * SRL $Rdst, $Rsrc, positions
: shift a
register’s bits right some number of positions, storing the result in
another * SRA $Rdst, $Rsrc, positions
: same as the above,
but copying the sign bit * LI $Rdst, constant
: set a
register to some constant’s value * LA $Rdst, label
: load a
register with the address of a labelled location in the data segment *
MOVE $Rdst, $Rsrc
: copy a value from one register into
another * LW $Rdst, ($Rtgt)
: load a register from memory at
an address
* SW $Rsrc, ($Rtgt)
: store a register into memory at an
address
* LW $Rdst, offset($Rtgt)
: load a register from memory at
an address at an offset * SW $Rsrc, offset($Rtgt)
: store a
register into memory at an address at an affset *
LB $Rdst, ($Rtgt)
: load a register with a byte in memory at
an address
* SB $Rsrc, ($Rtgt)
: store a byte of a register into memory
at an address
* BLT $Rsrc1,$Rsrc2,label
: jump to a line if one register’s
value is less than another. Also GT
, GE
,
LE
, EQ
, and NE
. *
B label
: jump to a line if one register’s value is less
than another. Also GT
, GE
, LE
,
EQ
, and NE
.
The registers are v0
, v1
,
a0-a3
, t0-t9
, s0-s7
,
gp
, sp
, fp
, and ra
.
You shouldn’t use the last four explicitly, unless you’ve decided to
make it an exercise for yourself to write a MIPS32 function using
calling conventions.
Exercises
Exercise 1: guessing six
The MIPS32 program guess.s
interacts with its user when
run in SPIM, helping them guess the hidden number that’s stored in its
.data
memory segment. Modify this to be a program
guess6.s
that only allows its user to make at most 6
quesses. It should tell them
You ran out of guesses. My number is XX.
on a single line,
when they fail to guess the number after 6 guesses. (Here
XX
should be the value of the correct guess.) Also, it
should tell them how many guesses they have left with the line
You have Y guesses.
just before they request the next
guess. (Here Y
should be the number of guesses that have
left.)
It should work with any hidden integer between 1 and 100.
BONUS We’ve chosen a limit of 6 when the number to
guess is in the range 1 to 100 because the logarithm of 100 using base 2
is 6. Make the program determine the number of guesses from the
.word
stored at the label max
, and so is
calculated from the number stored at that label. I’d think the limit
should be chosen such that the probability that they lose the guessing
game, assuming they make reasonable guesses, is between 1/4th and 1/2.
I’d think they’d want to keep playing if set up that way.
Exercise 2: only smaller values
I’ve included a MIPS32 program output_array.s
that scans
through the values stored in memory at the address labelled
array
and prints them out. It learned the number to print
by reading the data stored at the label length
.
Modify its code as a new program smaller.s
that only
outputs array entries when they immediately follow a value that’s larger
than them. For example, the top of the sample program has this
.data
declaration
length: .word 10
array: .word 6, 12, 89, 78, 90, 137, 5, 18, 10, 1000
and so running smaller.s
with this should yield the
output
78
5
10
It should work correctly when length
and
array
are set differently than the example.
Exercise 3: binary palindromes
The number 92 has the binary representation 1011100
because 92 = 64+16+8+4. And so the number 93 has the binary
representation 1011101
. That second code for 93 is a
palindrome because it reads the same forwards as it does backwards, but
the representation for 92 does not. The binary representation of 85 is
also a palindrome.
Write a program that takes two integers and outputs only the integers
in that range whose bit representations are palindromes. For example,
running it should lead to this interaction:
Enter the start: 73
Enter the end: 119
73
85
93
99
107
119
I’ve include bits.s
, bitsInReverse.s
, and
multiply.s
from Lecture 10-1 so that you
can see the shift operations in use.
Exercise 4: reversing a linked list
The C++ code below does the work of reversing a linked list
list
:
node* prev = nullptr;
node* curr = list->first;
while (curr != nullptr) {
node* next = curr->next;
curr->next = prev;
prev = curr;
curr = next;
}
list->first = prev;
Add a section to the linked list MIPS32 program
inorder_llist.s
as a new program
inorder_reverse.s
so that, after it traverses and prints
out the contents of a sorted linked list, it then reverses the nodes in
that linked list. It should so that be relinking the nodes similar to
how the C++ code above does. Finally, have it traverse and print the
resulting linked list.
You should be able to just cut and paste the code that outputs the
linked list after your reversal code. The second output should show the
data to be in reverse sorted order.