CO Lab Manual
Course Page
  • Course Information
    • Welcome
    • Introduction
    • Your Contributions
    • Lab Sessions and Etiquette
    • Team Setup
    • Assumed Prior Knowledge
  • Setup Guides
    • GitHub Repository Setup
    • Technical Setup
      • Windows
      • Linux
      • macOS
    • GitHub SSH Setup
    • Framework Setup
  • Reference Documentation
    • Introduction to the Documentation
    • A Brief History Lesson
    • Syntax (Intel vs. AT&T)
      • Section Exercises
    • Memory
      • Memory Management
      • Section Exercises
    • Registers
      • Section Exercises
    • Instructions
    • Subroutines
      • Calling Subroutines
      • Writing Subroutines
      • Section Exercises
    • Input/Output
      • Printing to the Terminal
      • Reading from the Terminal
      • Section Exercises
    • Programming Constructs
    • Assembler Directives
    • C/C++ vs Assembly
    • Building and Running Programs
    • Address Sanitization
    • A0: A Running Example
  • Assignments
    • Introduction to the Assignments
    • Mandatory Assignments
      • A1: Subroutines and I/O
      • A2: Recursion
    • Extra Assignments
      • A3-a: Fibonacci Calculator
      • A3-b: Fibonacci REPL
      • A4: Diff
      • A5: Printf
      • A6: HPC
      • A7: Bitmap
      • A8: Game
  • Appendix
    • Acknowledgments
    • Rules and Regulations
    • Frequently Asked Questions
    • How to use a Debugger
Powered by GitBook
On this page
  • Printf
  • Assignment (500 points)
  • Format Specifiers
  • Library Functions
  • Main Program
  • Bonus (250 points)
  1. Assignments
  2. Extra Assignments

A5: Printf

500 - 750 points

CMake target: a5

cmake --build .build --target a5

You probably have used the printf (Linux man page: man printf) function (or its relatives) many times already. With that, you likely have come to love and appreciate the abstractions it offers. If you haven't, there is a chance you will do so after having finished this assignment.

Ignoring its deserved place in the coding hall-of-fame, printf is just another function like any other. To prove that (because it needs to be proven, why should you just trust us here?!) in this assignment you will implement your own printf function, that matches the original in quite some of its functionality.


Printf

The printf function is pretty flexible, especially in its number of arguments. How many arguments do you need to give it? 1. How many arguments can you give it? Well, pretty much unlimited.

printf takes a variable number of arguments, so the argument count is not fixed in its signature. The first argument is always the so-called format string. This argument is a pointer to a memory location of the first character of the string to print. This string, however, may not only include "regular" characters but also so-called format specifiers (yes that's the official name of the %ds or %us that you've been using so far). Whenever the function encounters such a specifier in the format string it will look at the next argument in the argument list for the correct substitution (at least for most specifiers, depending on the type).


Assignment (500 points)

Implement a (simplified) my_printf subroutine. Unlike the full printf, your version only has to understand the format specifiers listen below. If a format specifier is not recognized, it should be printed without modification. Your function must follow the x86_64 calling conventions. It must accept any number of arguments (so even tens or hundreds), like any standard printf implementation.

void my_printf(char *fmt, ...);

Note that, compared to the original implementation, your subroutine will not return any value. Regularly, printf will return the length of the formatted string printed to standard output. You do not have to support this feature in your implementation.

Format Specifiers

Your implementation should support the following format specifiers:

  • %d: print a signed, 32-bit integer in decimal

  • %u: print an unsigned, 32-bit integer in decimal

  • %s: print a null-terminated string - no format specifiers should be parsed in this string

  • %%: print a percentage sign

Example:

Suppose you have the following format string:

"My name is %s and I am %u years old. My favorite ASCII character is %%."

and the additional arguments: "Lennart" and 21, then the output of your subroutine should be:

My name is Lennart and I am 21 years old. My favorite ASCII character is %.

Library Functions

You are not allowed to use any C library functions except putchar (Linux man page: man putchar) in your implementation. A working solution that uses additional library functions will not be accepted.

You are of course encouraged to structure your implementation using helper functions written by yourself (in Assembly).

Main Program

The a5-printf.S file includes a main subroutine. You should use this subroutine to test your implementation against the real printf call. However, your main subroutine will be ignored in grading and by the automatic tests.

CodeGrade provides a series of tests that are automatically compared to the real implementation of printf. When failing any of these tests, you will be shown the exact my_printf call used, including the format string and parameters.

my_printf(FMT=My number: %d\n, ARG=(int32_t) 55)
[ERROR] my_printf did not match printf!
Expected output:
	My number: 55

Actual output:
	My number: ((not implemented))

Use the output to recreate any issues locally. In the example above, the call was my_printf("My number: %d\n", 55) and the expected output was My number: 55.


Bonus (250 points)

  • width specifiers, both as part of the format specifier and as an additional argument (represented by an asterisk in the format specifier)

  • the minus, plus, space, and zero flags - only for %d and %u specifiers

  • any combination of flags in any order

It is extremely important to fully understand how these flags work before implementing your subroutine. Play around with printf and see how different calls behave when including special flags.

Additionally, you should see what happens when you pair conflicting parameters, such as the plus and the zero flags.

PreviousA4: DiffNextA6: HPC

Last updated 4 months ago

Your implementation so far can print basic signed and unsigned numbers. A large part of the functionality of printf, however, comes from the additional formatting options that can be specified. To get an additional 250 bonus points, you have to add support for width options including some flags (see the list below) to your implementation. You can find a comprehensive definition in any C standard library reference (like ). Your implementation must support all of the following:

Once you fully understand their functionality, you should set up a testing suite in your main subroutine. Always compare your output closely to the real printf implementation, perhaps analyzing the differences using or the .

this one
your diff implementation
real diff