mirror of
https://github.com/janishutz/eth-summaries.git
synced 2026-01-12 20:28:31 +00:00
[SPCA] Stack
almost complete, still missing variadic functions
This commit is contained in:
@@ -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)).
|
||||
\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{imulX} & \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{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{tables}{lll}{\texttt{setX} & Condition & Description}
|
||||
@@ -71,7 +71,7 @@ and \texttt{SF} is set if \texttt{a \& b < 0}.
|
||||
|
||||
\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}
|
||||
cmpl %eax, %edx
|
||||
|
||||
@@ -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|.
|
||||
|
||||
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}
|
||||
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|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}
|
||||
|
||||
@@ -1 +1,52 @@
|
||||
\newpage
|
||||
\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.
Reference in New Issue
Block a user