[SPCA] Fix various errors

This commit is contained in:
2026-01-23 10:33:49 +01:00
parent b86fd00a60
commit 25b3381294
15 changed files with 36 additions and 23 deletions

View File

@@ -29,11 +29,11 @@ int get_user_input_int( char prompt[] ) {
printf( "Hello World\n" );
}
// Inversed while loop (executes at least once)
// Inverted while loop (executes at least once)
do {
input_data -= 1;
input_data_copy -= 1;
printf( "Bye World\n" );
if ( input_data_copy == 0 )
if ( input_data_copy == 10 )
goto this_is_a_label;
} while ( input_data_copy > 1 );

View File

@@ -30,6 +30,7 @@ int main( int argc, char *argv[] ) {
assert( arr == &( arr[ 0 ] ) ); // Evaluates to true
int new_arr[ 3 ] = arr; // Compile time error (cannot use other array as initializer)
int *new_arr_p = &arr[ 0 ]; // This works
void *t;
a_function( &get_user_input_int, c_arr );

View File

@@ -2,7 +2,7 @@
int main( int argc, char **argv ) {
int a[ 2 ];
int *b = malloc( 2 * sizeof( int ) ), *c;
int *b = (int *) malloc( 2 * sizeof( int ) ), *c;
a[ 2 ] = 5; // assign past the end of an array
b[ 0 ] += 2; // assume malloc zeroes out memory
c = b + 3; // mess up your pointer arithmetic

View File

@@ -35,6 +35,6 @@ struct coroutine *co_new( co_start_fn *start, void *ctxt ) {
co->start = start;
co->arg = ctxt;
setjmp( co->env );
co->env[ 0 ].__jmpbuf[ 6 ] = ( (uint64_t) ( co->stack ) + CORO_STACK_SIZE ); // Machine specific
co->env[ 0 ].__jmpbuf[ 7 ] = ( (uint64_t) ( start_cl ) ); // Machine specific
co->env[ 0 ].__jmpbuf[ 6 ] = ( (uint64_t) ( co->stack ) + CORO_STACK_SIZE );
co->env[ 0 ].__jmpbuf[ 7 ] = ( (uint64_t) ( start_cl ) ); // Both lines machine specific
}

View File

@@ -11,12 +11,13 @@ The following condition codes were covered in the lecture (operation: \texttt{t
\content{Explicit computation}
In the below explanations, we always assume \texttt{src2 = b} and \texttt{src1 = a}
To explicitly compute them, we can use the \texttt{cmpX src2, src1} instruction (with X again any of the size postfixes),
To explicitly compute them, we can use the \texttt{cmpX src2, src1} (i.e. for easier understanding, \texttt{cmpX b, a}) instruction (with X again any of the size postfixes),
that essentially computes $(a - b)$ without setting a destination register.
When we execute that instruction, \texttt{CF} is set if \texttt{a < b} (unsigned), \texttt{ZF} is set if \texttt{a == b}, \texttt{SF} is set if \texttt{a < b} (signed)
and \texttt{OF} is set as above, where \texttt{t = a - b}.
Another instruction that is used is \texttt{testX src2, src1} (X again a size postfix), and acts like computing \texttt{a \& b} and where \texttt{ZF} is set if \texttt{a \& b == 0}
Another instruction that is used is \texttt{testX src2, src1} (X again a size postfix, easier: \texttt{testX b, a}), and acts like computing \texttt{a \& b} and where \texttt{ZF} is set if \texttt{a \& b == 0}
and \texttt{SF} is set if \texttt{a \& b < 0}.
\content{Zeroing register} We can use a move instruction, but that is less efficient than using \texttt{xorl reg, reg}, where \texttt{reg} is the 32-bit version of the reg we want to zero.

View File

@@ -1,8 +1,8 @@
\subsubsection{Jumping}
To jump, use \texttt{jmp <label>} (unconditional jump) or the \texttt{jC} instructions, with \texttt{C} from table \ref{tab:condition-codes}
To jump, use \texttt{jmp <label>} (unconditional jump) or the \texttt{jC <label>} instructions, with \texttt{C} from table \ref{tab:condition-codes}
\begin{table}[h!]
\begin{tables}{lll}{\texttt{setX} & Condition & Description}
\begin{tables}{lll}{\texttt{setC} & Condition & Description}
\texttt{e} & \verb|ZF| & Equal / Zero \\
\texttt{ne} & \verb+~ZF+ & Not Equal / Not Zero \\
\texttt{s} & \verb|SF| & Negative \\
@@ -23,11 +23,11 @@ To jump, use \texttt{jmp <label>} (unconditional jump) or the \texttt{jC} instru
Similar to \texttt{jC}, the same postfixes can be applied to \texttt{cmovC}, for example:
\begin{minted}{gas}
cmpl %eax, %edx
cmovle %edx, %eax
cmpl %eax, %edx # computes (edx - eax) without overwriting edx
cmovle %edx, %eax # only copies edx into eax if edx <= eax
\end{minted}
Will move \verb|%edx| into \verb|%eax|, only if \verb|%edx| is less or equal (\verb|le|) \verb|%eax|.
Due to the computed condition flags, this will move \verb|%edx| into \verb|%eax|, only if \verb|%edx| is less than or equal (\verb|le|) to \verb|%eax|.
This can be used to, for example, compile ternary expressions from \verb|C| to Assembly.
However, this requires evaluating both possible expressions, which may lead to a (significant) performance overhead.

View File

@@ -32,7 +32,7 @@ The same function, using a \verb|while| loop instead may lead to this:
\verb|for| loops follow the same idea as \verb|while| loops, albeit with a few more jumps.
\verb|switch| statements are implemented differently depending on size and case values:
Sparse switch statements are compiled as decision trees, whereas large switch statements may become \textit{jump tables}.
Sparse switch statements are compiled as decision trees, whereas compact switch statements may become \textit{jump tables}.
These jump tables are usually stored in the \texttt{.rodata} section with 8-byte alignment. The jump uses offsets:
\mint{gas}|jmp *.LABEL(, %rsi, 8)|

View File

@@ -1,5 +1,6 @@
\newpage
\subsection{The Stack}
\label{sec:asm-stack}
The Stack is the main way to dynamically allocate memory in Assembly, i.e. for temporary values. This process is completely manual: Allocating/Deallocating memory on the stack is entirely explicit. The stack grows \textit{downwards}: Addresses decrease as the stack grows.
The Stack pointer \verb|%rsp| points to the current top of the stack.

View File

@@ -7,6 +7,7 @@ We can implement that either by rewriting the functions into a single function,
A way around this is to use \bi{Continuations}, where the first function saves its state and the context is switched to the other function.
That function can then load its state and continue where it left off, runs until it finishes its task, then saves its state and the context switches back to the original function.
\inputcodewithfilename{c}{}{code-examples/01_asm/10_coroutine.h}
\newpage
\inputcodewithfilename{c}{}{code-examples/01_asm/10_coroutine.c}
As you can see, the \texttt{setjmp.h} functions are the foundation of all concurrent programming.

View File

@@ -75,12 +75,12 @@ It is even possible to do this:
\rmvspace
\content{Namespaces}
\lC\ has a few different namespaces, i.e. you can have the one of the same name in each namespace (i.e. you can have \texttt{struct a}, \texttt{int a}, etc).
\lC\ has a few different namespaces, i.e. you can have one of the same name in each namespace (i.e. you can have \texttt{struct a}, \texttt{int a}, etc).
The following namespaces were covered:
\rmvspace
\begin{itemize}[noitemsep]
\item Label names (used for \texttt{goto})
\item Tags (for \texttt{struct}, \texttt{union} and \texttt{enum})
\item Member names one namespace for each \texttt{struct}, \texttt{union} and \texttt{enum}
\item Tags (for \texttt{struct}, \texttt{union} and \texttt{enum} names)
\item Member names (one namespace for each \texttt{struct}, \texttt{union} and \texttt{enum})
\item Everything else mostly (types, variable names, etc, including typedef)
\end{itemize}

View File

@@ -5,6 +5,12 @@ In Table \ref{tab:c-operators}, you can see an overview of the operators, sorted
You may notice that the \verb|&| and \verb|*| operators appear twice. The higher precedence occurrence is the address operator and dereference, respectively,
and the lower precedence is \texttt{bitwise and} and \texttt{multiplication}, respectively.
Additionally, \verb|+| and \verb|-| also appear twice, the higher precedence one being a unary plus or minus, respectively, which is used to denote positive or negative numbers,
and it can also be used to do a sort-of assertion that we have an arithmetic type using the preprocessor macro
\mint{c}|#define CHECK_ARITHMETIC(x) (+(x))|
which will cause a compiler error if \texttt{x} is for example a pointer.
Of course, the lower precedence \verb|+| and \verb|-| is addition and subtraction, respectively.
Very low precedence belongs to boolean operators \verb|&&| and \texttt{||}, as well as the ternary operator and assignment operators
\begin{table}[h!]
\begin{tables}{ll}{Operator & Associativity}
@@ -34,7 +40,7 @@ Very low precedence belongs to boolean operators \verb|&&| and \texttt{||}, as w
\item Right-to-left: \texttt{A += B += C} $\mapsto$ \texttt{(A += B) += C}
\end{itemize}
As it should be, boolean and, as well as boolean or support early termination.
As it should be, boolean and, as well as boolean or, support early termination.
The ternary operator works as in other programming languages \verb|result = expr ? res_true : res_false;|

View File

@@ -4,7 +4,7 @@ On loading of a program, the OS creates the virtual address space for the proces
before other preparations like final linking and relocation are done.
Stack-based languages (supporting recursion) allocate stack in frames that contain local variables, return information and temporary space.
When a procedure is entered, a stack frame is allocated and executes any necessary setup code (like moving the stack pointer, see later). % TODO: Link to correct section
When a procedure is entered, a stack frame is allocated and executes any necessary setup code (like moving the stack pointer, see \ref{sec:asm-stack}).
When a procedure returns, the stack frame is deallocated and any necessary cleanup code is executed, before execution of the previous frame continues.
\bi{In \lC\ a pointer is a variable whose value is the memory address of another variable}
@@ -19,13 +19,15 @@ The (Linux)-Kernel randomizes the address space to prevent some common exploits.
\end{scriptsize}
\content{Pointer Arithmetic} Note that when doing pointer arithmetic, adding $1$ will move the pointer by \texttt{sizeof(type)} bits.
Pointer arithmetic with a \texttt{void} pointer is thus not allowed by standard \lC, as the compiler does not know the size of the data type.
However, \texttt{gcc} does allow it and assumes the size of \texttt{void} is \texttt{1 byte}.
You may use pointer arithmetic on whatever pointer you'd like (as long as it's not a null pointer).
This means, you \textit{can} make an array wherever in memory you'd like.
The issue is just that you are likely to overwrite something, and that something might be something critical (like a stack pointer),
thus you will get \bi{undefined} behaviour! (This is by the way a common concept in \lC, if something isn't easy to make more flexible
(example for \texttt{malloc}, if you pass a pointer to memory that is not the start of the \texttt{malloc}'d section, you get undefined behaviour),
in the docs mention that one gets undefined behaviour if you do not do as it says so\dots RTFM!)
in the docs mention that one gets undefined behaviour if you do not do as it says, so\dots RTFM!)
As already seen in the section arrays (section \ref{sec:c-arrays}), we can use pointer arithmetic for accessing array elements.
The array name is treated as a pointer to the first element of the array, except when:

View File

@@ -4,7 +4,7 @@ The advantage of having denormalized values is that 0 can be represented as the
\content{Example} $8$b Floating Point table to visualize the different cases.
$$
8\text{b precision Floating Point:}\quad \underbrace{0}_s \underbrace{0000}_c \underbrace{000}_m
8\text{b precision Floating Point:}\quad \underbrace{0}_s \underbrace{0000}_e \underbrace{000}_m
$$
\renewcommand{\arraystretch}{1.2}

View File

@@ -52,9 +52,10 @@ in \texttt{C}, function symbols can explicitly be declared weak using:
The second step during Linking is Relocation.
Code and data sections of separate sources are combined, and symbols are relocated from relative locations (in \texttt{.o} files) to absolute locations (in \texttt{.exe} files)
Code and data sections of separate sources are combined, and symbols are relocated from relative locations (in \texttt{.o} files) to absolute locations (in executable files)
\textbf{Command line order matters} for this, since the Linker will scan \texttt{.o} and \texttt{.a} files in this order. In general, libraries should therefore be linked \textit{last}.
\textbf{Command line order matters} for this, since the Linker will scan \texttt{.o} and \texttt{.a} files in the order they are appear in the CLI arguments.
In general, libraries should therefore be linked \textit{last}.
\newpage
\subsubsection{Packaging Libraries}

Binary file not shown.