Question 5

Deadline Friday, October 20, 11:59pm
Name on Marmoset Q5
To Submit decimal.asm

MIPS Assembly Programming, Part I

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:

In this question, you will use the input and output features of MIPS assembly language.

Input & Output in MIPS Assembly

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

MIPS Assembly Language Reference

The following reference sheet gives a brief overview of all the instructions available in our simplified CS 241 dialect of MIPS assembly language.

Reading Decimal Numbers

Motivation

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.

Don't forget to return with jr $31 when you're finished.

Clarifications

You can make the following assumptions about the input:

You will not receive input that does not meet these specifications, and no error checking is required.
Expected Output

For valid input, the expected output is the same as the following C++ program:

#include <iostream>
int main() { 
  int n;  std::cin >> n; 
  std::cout << (char) n;
}

Here is a one-line command to assemble and run your program with a given input on the Linux servers (taking advantage of Bash's process substitution feature):
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.