Assignment 6: Implementing myprintf()

The goal of this assignment is to implement and use leaf functions, recursive functions, decimal to string conversions, variable length argument lists, and C linkage in SPARC assembly code.

In this assignment, you will write a modified version of the printf() function in SPARC assembly code which can be called from a C program.

The ANSI C prototype for the myprintf() function is as follows:

    void myprintf(const char *format, ...);
The first argument is a required format string. It is followed by zero or more optional arguments. The number of arguments needed is determined by the contents of the format string. The output of the function is sent to the standard output (file descriptor 1) using the write service request and the trap instruction.

The format contains two kinds of items: plain characters and conversion specifications. Plain characters are simply copied to the standard output. Conversion specifications begin with a % and end with a conversion operation character from the set: u, s, and %.

%u interprets the next argument in the parameter list as a 32-bit unsigned integer and prints its decimal representation.

%s interprets the next argument in the parameter list as the address (a pointer) of a null-terminated character string (type const char *) which is printed. If the address is 0 (i.e., NULL), the behavior is as if a pointer to the string "NULL" were supplied.

%% causes a single percent sign to be printed. This does not consume an argument from the argument list.

Anything not listed above is not a conversion specification and is printed verbatim. See the example below.

The format argument is the address of the format string, and the format string is terminated by a null character (ascii code 0).

If a NULL pointer is passed as the first parameter, myprintf() should behave as if a pointer to the string "NULL\n" were given as the format string.

Example

Given the program:
extern void myprintf(char *, ...);

int main(void)
{
   myprintf("Simple Test\n");
   myprintf("Simple Test with ignored arguments\n", 1, 2, 3);
   myprintf(NULL);
   myprintf("%s\n", "Hello, World");
   myprintf("%s\n", NULL);
   myprintf("0=%u  4294967295=%u\n", 0, 4294967295UL);
   myprintf("%u%% is perfect\n", 100);
   myprintf("%100xs\n", "Not Used");
   myprintf("%1u %1r %1%\n");
   myprintf("%s", "Go" "od");
   myprintf("%s\n", "bye");

   return 0;
}
The output is:
Simple Test
Simple Test with ignored arguments
NULL
Hello, World
NULL
0=0  4294967295=4294967295
100% is perfect
%100xs
%1u %1r %1%
Goodbye

Ground Rules

These rules are designed to constrain the number of possible solutions. This will make the assignment easier to grade and help meet the goals stated at the beginning of the assignment.

Suggestion

My solution used eight helper functions in addition to the myprintf() function. I suggest you first implement and test this program using C. Write drivers which will test the helper functions. Now, one at a time, create an equivalent SPARC routine for each C function. Start with a simple leaf function (such as the one which print one char to stdout). Link it with your working program so that everything is in C except for this low-level function. Test it carefully. Continue by translating and testing each function until at last myprintf() is complete.
To help you understand how to implement variable length argument list, we have provided you a sample program myputs under ~cs217/Assignment6/.
You can use the macro definitions in the book if you like, but remember you must submit processed assembly code. You will not receive credits if you submit a file with macros in it.

Submission

Submit your file electronically with the command:
/u/cs217/bin/submit 6 myprintf.s
Due: submitted by 11:59pm, Wednesday, April 11, 2001.


Copyright © 1998 by Scott C. Karlin