| Deadline | Friday, October 20, 11:59pm |
| Name on Marmoset | Q5 |
| To Submit |
decimal.asm
|
This is the first of several questions that will involve programming in MIPS assembly language.
To assemble your program (i.e., convert it into machine code)
you can use the course tool cs241.binasm.
You can then run the machine code program with one of our MIPS emulators:
mips.twoints, which takes two integers as input
and stores them in $1 and $2 before running the program.mips.stdin, which just runs the program with no
setup; this is intended for programs that work by reading from standard input.mips.array, which asks you to specify the elements of an array,
allocates the array in memory after the end of your program, stores the
starting address of the array in $1, and stores the number of elements in $2.
In this question, you will use the input and output features of MIPS assembly language.
Input: If you load (with lw) from the special address
0xffff0004,
MIPS will read one byte (8 bits) from standard input and store the byte in
the destination register (padded with 0s to turn it into a 32-bit word).
If there are no bytes left to read (the "end of file" is reached) then the
destination register will contain 0xffffffff
(the two's complement encoding of -1).
Output: If you store (with sw) to the special address
0xffff000c, MIPS will take the least significant byte
(rightmost 8 bits) of the source register and write this byte to
standard output.
Example: Read a byte from standard input, then print the byte to standard output, followed by a newline (ASCII 0x0a).
lis $20 .word 0xffff000c ; output address lis $21 .word 0xffff0004 ; input address lis $10 .word 0x0A ; newline character lw $3, 0($21) ; read byte sw $3, 0($20) ; write byte sw $10, 0($20) ; write newline jr $31
Suppose this program is stored in a file called example.asm.
We can assemble this file as follows (after running source /u/cs241/setup):
cs241.binasm < example.asm > example.mips
Now, let's run the MIPS machine code with mips.stdin,
and provide it some input on standard input.
(Here we are just using Bash's <<< syntax for providing a single-line string as input.)
mips.stdin example.mips <<< "A" Running MIPS program. A MIPS program completed normally. $01 = 0x00000000 $02 = 0x00000000 $03 = 0x00000041 $04 = 0x00000000 $05 = 0x00000000 $06 = 0x00000000 $07 = 0x00000000 $08 = 0x00000000 $09 = 0x00000000 $10 = 0x0000000a $11 = 0x00000000 $12 = 0x00000000 $13 = 0x00000000 $14 = 0x00000000 $15 = 0x00000000 $16 = 0x00000000 $17 = 0x00000000 $18 = 0x00000000 $19 = 0x00000000 $20 = 0xffff000c $21 = 0xffff0004 $22 = 0x00000000 $23 = 0x00000000 $24 = 0x00000000 $25 = 0x00000000 $26 = 0x00000000 $27 = 0x00000000 $28 = 0x00000000 $29 = 0x00000000 $30 = 0x01000000 $31 = 0x8123456c
Notice that A (followed by a newline) is printed in between "Running MIPS program" and "MIPS program completed normally".
If you only want to see standard output and suppress the other information, you can redirect standard error to /dev/null:
mips.stdin example.mips <<< "A" 2> /dev/null A
The following reference sheet gives a brief overview of all the instructions available in our simplified CS 241 dialect of MIPS assembly language.
To translate the assembly language line .word 241
into a 32-bit binary word, you need to convert the string "241"
and to an actual integer.
In C++, you might do this with a function like stoi,
or using stream extraction with an int variable.
In Racket, you could use string->number.
If you couldn't rely on the standard library of a high-level language, how would you implement this functionality? Let's write a simple version – for 8-bit numbers only – in MIPS assembly.
Write a MIPS assembly program that reads (from standard input) a string representing a single decimal number in the range -128 to 255, terminated by a newline.
jr $31 when you're finished.
You can make the following assumptions about the input:
For valid input, the expected output is the same as the following C++ program:
Clarifications
You will not receive input that does not meet these specifications,
and no error checking is required.
Expected Output
#include <iostream>
int main() {
int n; std::cin >> n;
std::cout << (char) n;
}
mips.stdin <(cs241.binasm < decimal.asm) <<< "33" Running MIPS program. !MIPS program completed normally. $01 = ...Notice that "MIPS program completed normally" has a
!
character before it. This is because 33 is the ASCII code (in decimal)
for an exclamation mark. This byte was printed and the terminal
interpreted it as an ASCII character.
To confirm that your output is correct for bytes that are not printable ASCII characters, you could perhaps redirect the output to a file, and examine the file using the same techniques you used in Question 1.