Low-level processor-specific symbolic language. We focus on user-mode x86 64-bit assembly, AT&T syntax.
Program composed of
.data
is section with variables.text
is section with code.byte
/.word
/.long
/.quad
defines integer (8/16/32/64 bits).ascii
/.asciz
defines string (without/with terminator)#
is ignoredForm: mnemonic source, destination
mnemonic
is short code telling CPU what to do (mov
, add
, push
, pop
, call
, jmp
, etc.)
b
for byte, w
for 16-bit word, l
for 32-bit long, q
for 64-bit quad)source
and destination
are operands
%rax
, %rsp
, %al
)
displacement(base, index, scale)
displacement+base+(index*scale)
base
, index
64-bit registersdisplacement
32-bit constant or symbol (default 0)scale
is 1, 2, 4, or 8 (default 1)%rax
, %rbx,
%rcx,
%rdx,
%rsi,
%rdi,
%r8-
%r15`
%rax
, low 32 bits is %eax
, 16 bits is %ax
, high 4 bits is %ah
, low 4 bits is %al
%rsp
%rbp
%rip
%cs
, %ds
, etc.%crN
, %drN
, MSRs – only used in OS kernel)%stN
, %mmN
, %xmmN
, %ymmN
– only used with special instructions)0x401000
, 8(%4bp)
, (%rdx, %rcx, 4)
)$42
, $0x401000
, only for source)Intel uses little endian ordering – from lowest address, you lay out bytes from the end (little address has end bytes)
Signed integers expressed in 2’s complement – sign change by flipping bits and adding one.
Comparisons:
cmp src1, src2
is like src2 - src1
but sets flags.test src1, src2
is like src1 & src2
but sets flagslea src, dst
is dst = &src
(src
is in memory)Conditional jumps
jcc addr
(or jncc
for not)addr
if cc
holds, decided using flags register
e
/z
: result == 0
b
: dst
< src
(unsigned, a
for above)l
: dst
< src
(signed, g
for above)s
: result
< 0 (signed)Data objects in data segment:
.data
myvar: .long 0x1234567, 0x23456789
bar: .word 0x1234
mystr: .asciz "foo"
Stack grows downwards (towards lower memory addresses).
Stack pointer (%rsp
) points to top of stack
Stack composed of frames, which are pushed on stack during function calls.
Address of current frame stored in frame pointer register (on Intel, %rbp
)
Each frame contains
Parameter passing in caller function for Linux
%rdi
, then %rsi
, %rdx
, %rcx
, %r8
, %r9
Prologue in called function
%rbp
) on to stack%rbp
to current stack pointer%rbx
, %r12-%r15
)sub $n, %rsp
with n the size of local vars)enter
opcode does everything except pushing callee-saved registersEpilogue in called function
%rax
ret
leave
restores stack pointer and ret
s