CS61C Fall 2006

Project 02
sprintf for MIPS

TA in charge: Sameer Iyengar

Updates

Purpose

Gain experience with:

and generally become an all-around totally awesome assembly programmer.

Instead of one big, long, crazy project, we're going to do three smaller excercises.

Submission

To submit your project, create a directory named proj2 that contains: sprintf.s, div.s and fp.c (You can download these files from the links on this page or copy them from ~cs61c/lib/proj2/). From within that directory, type "submit proj2".

The project deadline is 11:59pm on Friday, 13th October.

Background: Before you start

Since there can be an arbitrary number of arguments to the sprintf function, all arguments will be passed on the stack instead of in registers $a0-$a3. Before your function is called, the caller will save arguments to the stack in the same way $s0-$s7 registers are saved. (By doing sw $s0, offset($sp)). In order to access these variables, you will need to figure out the correct offset in relation to the callee stack pointer.

For example, if the caller stores an argument in 0($sp), the callee might access the argument at 8($sp), depending on how the stack pointer is moved in the callee function. (NOTE: It is not always an offset of 8, it depends on how the stack is moved)

If this is at all confusing to you, please read this Tutorial on MIPS stack management with more detailed information and nifty diagrams.

Part 1: sprintf

Write a MIPS assembly language implementation of the C function sprintf:

int sprintf (char *outbuf, char *format, ...)

sprintf works like printf, except that it writes to the string outbuf instead of to standard output. outbuf already points to allocated space, that is large enough to hold the string.

Arguments:

Your function must accept any number of arguments, passed according to a non-MIPS standard conventions: All the arguments will be passed through the stack, with the first argument in the lowest stack position (meaning, the address closer to zero. Looking at the figures in the tutorial, this means closer the to top).

Return:

What you need to do:
You do not have to implement all of the formatting options of the real sprintf. Here are the ones you are to implement:

What you don't need to do (unless you really want to):

To run this project, you need to load two files in the correct order: run xspim and load test.sprintf.s. Next load sprintf.s. Finally, run your program. The following Makefile may make your life easier.

Part 2: division

Implement this division algorithm in MIPS. NOTE: You must use this recursive algorithm. Iterative solutions will receive zero (zip, nothing, nada) points.

Given x and y (in $a0 and $a1), return the quotient (q) and remainder (r) (in $v0 and $v1). You can treat x and y as unsigned.

I know what you're thinking so no, you may not use the div instruction (obviously). The only arithmetic operations you can do are addition, subtraction and bit-shifting.

divide(x, y)
   if x == 0: return (q, r) = (0, 0)
   (q, r) = divide( floor(x/2), y )
   q = 2 * q
   r = 2 * r
   if x is odd: r = r + 1
   if r >= y:
      r = r - y
      q = q + 1
   return (q, r)

Put your code in the framework given in div.s. This is not a not a long problem. It can be done in around 20 lines of MIPS.

Part 3: floating point

Fill in the function:

void fp(unsigned int f)
The function should print out a string corresponding to interpreting f as a floating point number using the guidelines below. You may find it useful to add a method that converts decimal numbers to binary numbers. Put your code in the framework in fp.c.

NOTE: Since there was an inconsistency between the spec and example code regarding minimum effort digit formatting, you may do one of two things when printing out the mantissa:

  1. Drop all the zeros from the end of the mantissa
  2. Print all 23 digits of the mantissa, including any trailing zeros
This only applies to Part 3!

The following table lists all the possibilities:

Single Precision Object Represented What you must write into the buffer
ExponentMantissa
00 zero [-]0
0nonzero ± denormalized number [-]denorm
1-254anything ± normalized number [-]mantissa_in_binaryb 2^([-]exponent_in_decimal)
2550 ± infinity [-]infinity
255nonzero NaN (Not a Number) [-]NaN

Sample cases:

NumberInterpreted as floating point
0xffff0000-NaN
0x7f800000infinity
0x00100000denorm
0x80000000-0
0x345543421.10101010100001101000010b2^(-23)


Miscellaneous Requirements