[SPCA] Stack

almost complete, still missing variadic functions
This commit is contained in:
2026-01-12 08:06:51 +01:00
parent 53c5e984b2
commit 639c147264
4 changed files with 65 additions and 8 deletions

View File

@@ -9,7 +9,7 @@ The following instruction formats are commonly used:
Arithmetic / logic operations need a size postfix (replace \texttt{X} below with \texttt{b} (1B), \texttt{w} (2B), \texttt{l} (4B) or \texttt{q} (8B)). Arithmetic / logic operations need a size postfix (replace \texttt{X} below with \texttt{b} (1B), \texttt{w} (2B), \texttt{l} (4B) or \texttt{q} (8B)).
\begin{tables}{lll}{Mnemonic & Format & Computation} \begin{tables}{lll}{Mnemonic & Format & Computation}
\texttt{addl} & \texttt{Src, Dest} & \texttt{Dest} $\gets$ \texttt{Dest + Src} \\ \texttt{addX} & \texttt{Src, Dest} & \texttt{Dest} $\gets$ \texttt{Dest + Src} \\
\texttt{subX} & \texttt{Src, Dest} & \texttt{Dest} $\gets$ \texttt{Dest - Src} \\ \texttt{subX} & \texttt{Src, Dest} & \texttt{Dest} $\gets$ \texttt{Dest - Src} \\
\texttt{imulX} & \texttt{Src, Dest} & \texttt{Dest} $\gets$ \texttt{Dest * Src} \\ \texttt{imulX} & \texttt{Src, Dest} & \texttt{Dest} $\gets$ \texttt{Dest * Src} \\
\texttt{salX} & \texttt{Src, Dest} & \texttt{Dest} $\gets$ \texttt{Dest << Src} \\ \texttt{salX} & \texttt{Src, Dest} & \texttt{Dest} $\gets$ \texttt{Dest << Src} \\
@@ -48,9 +48,9 @@ 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. \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.
\content{Reading condition codes} To read condition codes, we can use the \texttt{setX} instructions, where the \texttt{X} is to be substituted by an element of table \ref{tab:condition-codes} \content{Reading condition codes} To read condition codes, we can use the \texttt{setC} instructions, where the \texttt{C} is to be substituted by an element of table \ref{tab:condition-codes}
\content{Jumping} To jump, we have the \texttt{jmp <label>} instruction (unconditional jump) or the \texttt{jX} instructions, with \texttt{X} from table \ref{tab:condition-codes} \content{Jumping} To jump, we have the \texttt{jmp <label>} instruction (unconditional jump) or the \texttt{jC} instructions, with \texttt{C} from table \ref{tab:condition-codes}
\begin{table}[h!] \begin{table}[h!]
\begin{tables}{lll}{\texttt{setX} & Condition & Description} \begin{tables}{lll}{\texttt{setX} & Condition & Description}
@@ -71,7 +71,7 @@ and \texttt{SF} is set if \texttt{a \& b < 0}.
\content{Conditional Moves} \content{Conditional Moves}
Similar to \texttt{jX}, the same postfixes can be applied to \texttt{cmovX}, for example: Similar to \texttt{jC}, the same postfixes can be applied to \texttt{cmovC}, for example:
\begin{minted}{gas} \begin{minted}{gas}
cmpl %eax, %edx cmpl %eax, %edx

View File

@@ -3,7 +3,8 @@
Control flow structures from \verb|C| like \verb|if/else| or \verb|for| are compiled into assembly mainly using jumps and conditional \verb|move|. Control flow structures from \verb|C| like \verb|if/else| or \verb|for| are compiled into assembly mainly using jumps and conditional \verb|move|.
By the nature of Assembly and thanks to compilers optimizing aggressively, there is no \textit{single} definitive translation of the \verb|C| control structures: The compiler may translate it very differently depending on the context of the program. By the nature of Assembly and thanks to compilers optimizing aggressively, there is no \textit{single} definitive translation of the \verb|C| control structures:
The compiler may translate it very differently depending on the context of the program.
\subsubsection{Conditional statements} \subsubsection{Conditional statements}
A function using an \verb|if/else| construct to choose the maximum of $2$ numbers might compile like this: A function using an \verb|if/else| construct to choose the maximum of $2$ numbers might compile like this:
@@ -30,4 +31,9 @@ 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|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}. \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}.
These jump tables are usually stored in the \texttt{.rodata} section with 8-byte alignment. The jump uses offsets:
\mint{asm}|jmp *.LABEL(, %rsi, 8)|
and we jump to the effective address of \texttt{.LABEL + rsi * 8}

View File

@@ -1 +1,52 @@
\newpage
\subsection{The Stack} \subsection{The Stack}
In the below two, we can do this with $x = 1, 2, 4, 8$, each corresponding to a size prefix that is set with \texttt{X}
\bi{Stack push} \texttt{pushX src}: Fetch operand at \texttt{src}, decrement \texttt{\%rsp} by $x$, then writes the operand at address of \texttt{\%rsp}
\bi{Stack pop} \texttt{popX dest}: Does the opposite, reads operand at \texttt{\%rsp}, increments it by $x$, then writes the operand into \texttt{dest}
\content{Procedure call / return} Use \texttt{call LABEL}. This pushes return label to the stack and jumps to the LABEL.
After this instruction, we also may use the \texttt{pushX} instruction to store further registers.
Just remember to pop in the correct order with the correct size again!
The \texttt{ret} instruction is the return instruction and it will jump back to the caller and execution will continue there.
\subsubsection{Calling Conventions}
The callee is the function that is called and the caller is the code / function that calls the function.
\begin{itemize}
\item \texttt{\%rax} and \texttt{\%eax} can be used without first saving (usually used as return)
\item Argument registers are caller saved (or not if not needed again)
\item \texttt{\%rsp} should not be modified anyway
\item \texttt{\%rbp} is callee saved and is used as frame pointer (usually set to equal \texttt{\%rsp} at start of procedure and can be used to access elements of the frame
(as it should not change during execution of the function and should always point to the start of the frame))
\end{itemize}
\begin{multicols}{2}
\begin{tables}{ll}{Name & Description}
\texttt{\%rax} & Return value, \#variable args \\
\texttt{\%rbx} & Base pointer, Callee saved \\
\texttt{\%rcx} & Argument 4 \\
\texttt{\%rdx} & Argument 3 (and return 2) \\
\texttt{\%rsi} & Argument 2 \\
\texttt{\%rdi} & Argument 1 \\
\texttt{\%rsp} & Stack pointer \\
\texttt{\%rbp} & Frame pointer, Callee saved \\
\end{tables}
\begin{tables}{ll}{Name & Description}
\texttt{\%r8} & Argument 5 \\
\texttt{\%r9} & Argument 6 \\
\texttt{\%r10} & Static chain pointer \\
\texttt{\%r11} & Temporary \\
\texttt{\%r12} & Callee saved \\
\texttt{\%r13} & Callee saved \\
\texttt{\%r14} & Callee saved \\
\texttt{\%r15} & GOT pointer, callee saved \\
\end{tables}
\end{multicols}
If we have more than 6 arguments to be passed, we can use the stack for this.
If we can do all accesses to the stack relative to the stack pointer, we do not need to
update \texttt{\%rbp} and not even \texttt{\%rbx}, or we can use it for other purposes.
We can also allocate the entire stack frame immediately by incrementing the stack pointer to the final position and then store data relative to it.
To deallocate a stack frame, simply increment the stack pointer

Binary file not shown.