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.
-
The only external functions you may use are .udiv.
-
The only service requests you may use are "write" and "exit". Only use
the "exit" service request if the "write" service request fails. For purposes
of this assignment, assume that the "write" service request fails if the
"C" bit is set after the trap or the number of characters actually written
did not match the number of characters requested to be written. Use the
"SYMBOL=value" construct in your program to give appropriate
symbolic names to
EXIT, WRITE, and STDOUT
-
Do not use the %rn names for the registers. Instead, use
the
%gn, %in, %ln, and
%on
names. You may not use the %Y register or the floating
point registers.
-
You are required to implement and use a recursive function which outputs
a 32-bit unsigned integer in decimal.
-
You are required to implement and use a leaf function which prints a character
on the standard output.
-
Begin your file with a comment block which includes your name. Precede
each function with a block of comments describing the function. The comments
will include: how the function is called (what goes in each register),
what the function does, the nature of the algorithm, and what (if anything)
is returned.
-
You must submit a single, plain SPARC assembly language file called
myprintf.s
which must assemble without warnings or errors using
lcc -c -o myprintf.o
myprintf.s. The name of the function must be myprintf().
-
You may not use a high-level language compiler such as gcc
or
lcc to generate the assembly code you submit.
-
You will lose points if you deviate from the assignment. Use the above
list as a final checklist for your program.
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