CS 208 s21 — Arithmetic in x86-64 Assembly
Table of Contents
1 Arithmetic Instructions
| Instruction | Description | Effect |
|---|---|---|
inc \(D\) |
\(D + 1 \rightarrow D\) | increment |
dec \(D\) |
\(D - 1 \rightarrow D\) | decrement |
neg \(D\) |
\(-D \rightarrow D\) | negate |
not \(D\) |
\(~D \rightarrow D\) | complement |
add \(S,\:D\) |
\(D + S \rightarrow D\) | add |
sub \(S,\:D\) |
\(D - S \rightarrow D\) | subtract |
imul \(S,\:D\) |
\(D * S \rightarrow D\) | multiply |
xor \(S,\:D\) |
\(D\,\widehat{}\,S \rightarrow D\) | exclusive-or |
or \(S,\:D\) |
\(D\,\vert\,S \rightarrow D\) | or |
and \(S,\:D\) |
\(D\,\&\,S \rightarrow D\) | and |
sal \(k,\:D\) |
\(D\) << \(k \rightarrow D\) |
left shift |
shl \(k,\:D\) |
\(D\) << \(k \rightarrow D\) |
left shift (same as sal) |
sar \(k,\:D\) |
\(D\) >> \(k \rightarrow D\) |
arithmetic right shift |
shr \(k,\:D\) |
\(D\) >> \(k \rightarrow D\) |
logical right shift |
2 Thinking in Assembly
2.1 Assembly to C
A C function with the signature long f(long *p, long i) compiled to the following assembly code:
f: movq %rsi, %rax addq (%rdi), %rax movq %rax, (%rdi) ret
| Register | Use |
|---|---|
%rdi |
1st argument (p) |
%rsi |
2nd argument (i) |
Possible C code for this function:
long f(long *p, long i) { long return_value = i; // move %rsi to %rax (%rax holds the return value for a function) return_value += *p; // dereference the pointer p, add that to %rax *p = return_value; // move the value in %rax to the memory location p points to return return_value; // return (using %rax as the return value) }
A more concise version that has the same effect:
long f(long *p, long i) { *p += i; return *p; }
2.2 leaq Instruction
- "load effective address", but more often "lovely efficient arithmetic"
- instead of reading from the memory location given by the source operand, copies the effective address to the destination
- generate pointers for later memory references
- can also do a muliply and an addition in a single instruction
leaq 7(%rdx, %rdx, 4), %raxwill set%raxequal to5 * %rdx + 7
- destination must be a register
- must have the
qsize designation on a 64-bit systemleaspecifically works with a memory addresses, which will always by 8 bytes on a 64-bit system
movq %rdx, %raxvsmovq (%rdx), %raxvsleaq (%rdx), %rax- rdx holds 0x100, memory address 0x100 holds 0xab