Assembly (Intel)
Compiling & Linking
| Bash | |
|---|---|
Basics
Exports & Sections
Symbols can be exported to be linked against with the linker
Every program in ELF has several sections:
data: global variablesrodata: global constants (read-only data)bss: space reserved at program startuptext: CPU instructions
| GAS | |
|---|---|
Labels & Declarations
Anything that's on the beginning of a line and is followed by a colon (:) is a label. Labels generally store addresses.
Declaration instructions:
db: declare bytesdw: declare word (2 bytes)dd: declare double word (4 bytes)dq: declare quad word (8 bytes)equ: set a name to the value of an expression
Note: See the NASM manual, section 3.2.1 for the full list. Note: all byte declarations are Little Endian
| GAS | |
|---|---|
Registers
There are several registers available on x86_64.
Some serve a specific purposes (e.g. registers for storing floating point ; numbers), while others are called "general purpose" registers.
There are 16 of them:
rax: accumulatorrbx: basercx: counterrdx: destinationrspandrbp: stack pointer and base pointerrsiandrdi: source and destination indexr8throughr15: lack of creativity
The prefix r means that instructions will use all 64 bits in the registers.
For all those registers, except r8 through r15, it's possible to access:
- the lowest 32 bits with
eprefix (e.g.eax,ebp) - the lowest 16 bits without any prefix (e.g.
ax,si)
For registers rax through rdx, it's possible to access:
- the lowest byte with the
lsuffix, replacing the trailingx(e.g.al) - the highest byt in the 16 bits with the
hsuffix, in the same way (e.g.ah)
Instructions
Instructions are operations that the CPU knowns how to execute directly.
They are separated from their operands by whitespace, and the operands are separated from other with commas.
| GAS | |
|---|---|
| GAS | |
|---|---|
add
Adds the two operands and stores the result in the destination.
| GAS | |
|---|---|
sub
Subtract the two operands and stores the result in the destination.
| GAS | |
|---|---|
mul, div, imul, idiv
mul and div interpret their operands as unsigned integers.
imul and idiv interpret their operands as signed integers in two's complement.
mul and div instructions take a single operand because they use fixed registers for the other number.
For mul, the result is rax * <operand>, and it's a 128-bit value stored in rdx:rax,
meaning the 64 lower bits are stored in rdx, while the 64 upper bits are stored in rax.
For div, the operand is the divisor and the dividend is rdx:rax,
meaning it's a 128-bit value whose 64 upper bits are in rdx and whose 64 lower bits are in rax.
The quotient is a 64-bit value stored in rax, and the remainder is also a 64-bit value, stored in rdx.
and, or, xor
shr, shl
| GAS | |
|---|---|
Note: there's sar for arithmetic right shift and sal for arithmetic shift left.