A0: A Running Example
This reference documentation introduced many concepts, definitions, and conventions that are important to know when programming in Assembly. You will likely need to revisit some of the pages once you start working on the assignments. However, most of it should eventually become part of your "inner manual" (also known as your intuition).
To help with this process of understanding and connecting the various concepts you have traversed, this page will discuss an algorithm, transform it into a formal specification, and finally build a running program for the specification.
Step 1: Algorithm
Eratosthenes of Cyrene lived in northern Africa from 276 B.C. to 194 B.C. and he devised what is probably the oldest known algorithm for finding prime numbers: the Sieve of Eratosthenes. The algorithm is not terribly efficient but it is very easy to understand, which is exactly why it is used here.
The algorithm starts by constructing a list of all numbers between 2 and some upper limit, in the case of this example 999:
As the first step, the first number of the list (2) is taken and all multiples of it are removed from the list, except 2 itself:
The process is repeated with the next number in the list (3), removing all multiples, except 3 itself:
The algorithm finishes after repeating the previous step, selecting the next number still in the list, until reaching the end of the list. After that, the list consists of all prime numbers until the upper limit.
Step 2: Specification
The next step on the way to a running program is to transform this algorithm into a formal specification. Why is this necessary? While the previous step describes the working steps of the algorithm, there are many technical details left out that need to be addressed before starting the implementation phase.
One of those details is the choice of representation: How shall the list of numbers be represented? One option would be to use a linked list structure, another option is to use a list of fixed size, such as an array. What implications for the complexity of the program does one choice have compared to the other? Resolving questions like this is a (critical) part of the creative challenge of programming, so usually you will have to decide on these matters yourself.
For this example, we will, instead of maintaining a list of remaining numbers, use an array of Boolean values, denoting for each index whether or not the number is still present. All entries of the array are initialized to true
; a number is removed by setting its corresponding table entry to false
.
The algorithm can now be translated to the following pseudocode description, written to closely resemble the C syntax:
This specification uses only simple operations on simple data types (integers and Booleans) and basic programming constructs such as loops and conditions. With the information given in this reference documentation, these constructs can easily be translated to the corresponding Assembly implementation, as will be shown in the next step.
Step 3: Implementation
The final step for getting a running program for the given algorithm is... well... to turn it into a running program. As the formal specification is already defined, this step can focus purely on the how of implementation, and no longer needs to address the what. As assembly languages are verbose by nature and require carefully thought-out instruction sequences, working with a formal specification greatly reduces the (reworking) effort for the implementation part.
Below is the x86-64 Assembly implementation of Eratosthenes' Sieve algorithm as defined in the formal specification of step 2. Try to read along and understand what is done and why, using the comments in the code and the subsequent explanations as a guide. Do not be intimidated by this example - the first programs you will write will be much simpler. However, after finishing all mandatory assignments, you should be able to follow and understand all parts of this program.
Note that the program is also part of the Lab Framework as part of the a0
folder, such that you can run/modify/test it on your machine.
Assembler Directives
The code contains various (pseudo-)instructions starting with a .
- take a look at the Assembler Directives page and try to understand what each of them is used for.
Registers, Variables, and the Stack
The algorithm specification uses a number of variables to store data, such as current
or the loop counter i
. The Assembly implementation handles some variables differently than others. Try to understand where each variable is stored and what might be the reason for that choice. It is important that you know the basics of Registers, including the concept of callee- and caller-saved registers, as well as the concepts of storing Local Variables on the stack.
Start & End of the Program
The beginning of the program (starting after the main
label) shows 2 instructions that are nowhere to be found in the pseudocode specification. These instructions are the Prologue of the main
routine. Their functioning is explained on the page about Subroutines.
The counterpart to the Prologue is the Epilogue, which constitutes the last 3 lines of the program:
I/O
If you examine the program code closely and try to follow along with the pseudocode, you will notice that the print(current)
instruction was translated to the following:
This is the Assembly implementation of the C instruction:
printing the value of current as a signed integer followed by a newline character. The specifics of this call are explained on the Printing to the Terminal page of this Manual.
Programming Constructs
The pseudocode specification uses two for
and one while
-loop. These loops are more or less directly translated from pseudocode to their typical Assembly representations. In the latter, however, they consist of multiple instructions and labels. The basics of these concepts are explained on the page about Programming Constructs.
Step 4: Your Turn!
Once you have arrived here, you have hopefully followed all preceding pages of this Lab Manual. Great! Actively reading the required material is the first, and arguably hardest, step on the journey through this Lab course. Even though all the concepts might still be a bit of a blurry mess in your mind, you can now start working on the practical assignments (maybe take a break first though). You may revisit many pages of this reference documentation throughout your work, but over time many concepts that seem complicated right now will start becoming natural to you.
Last updated