x86_64
, which means it’s the 64-bit variant of the x86 architecture-- hello.c --> | Preprocessor | -- hello.i --> | Compiler | -- hello.s --> | Assembler | -- hello.o --> | Linker | -- hello -->
byte
(suffix b
) = 1 byte = 8 bitsword
(suffix w
) = 2 bytes = 16 bitsdouble word
(suffix l
) = 4 bytes = 32 bitsquad word
(suffix q
) = 8 bytes = 64 bitschar
, short
, int
and long
To move into registers, between registers and between registers and memory, we use the mov
instruction:
mov Source, Destination
movq Source, Destination
, Destination movb Source
The Source
and Destination
above are what we call operands
There are three kinds:
$42
or $0x4F
%rax
(%rax)
We’ll talk about the last kind more next time
Example:
movq $52, %rax
movq %rax, %rbx
We also have multiple two-operand arithmetic instructions: add
, sub
, imul
, idiv
, and
, or
, xor
, etc.
They use the same general form as mov
and perform the operation on the two operands and store the result in the Destination
E.g.,
$3, %rax
addq imul %rax, %rbx
Exercise: 14 * (10 + 3)
- translate to assembly
There are also unary (single operand) instructions inc
, dec
, neg
, not
The single operand is also the destination
jmp
instruction (unconditional jump)To make decisions, we need to be able to jump conditionally
We can compare using the cmp
instruction
cmp Sub, Min
Performs Min - Sub
, but discards the result
Sub = subtrahend
Min = minuend
The next instruction is usually one of the following
je
- jump if equaljne
- jump if not equaljg
- jump if Min > Sub
jge
- jump if Min >= Sub
jl
- jump if Min < Sub
jle
- jump if Min <= Sub
There are a few more, but these should be enough for us
When programming conditional jumps, always pay attention to how the cmp
instruction works - in GNU assembly the sense is reversed
call
instructionmain
)call
takes one operand – the address of the function’s body – most often we will use a symbolic name that represents that addressprintf
is as simple as call printf
… or is it?Argument | Register |
---|---|
1 | %rdi |
2 | %rsi |
3 | %rdx |
4 | %rcx |
5 | %r8 |
6 | %r9 |
%rax
%rbx
, %rbp
, and %r12
–%r15
all argument registers (see above), the return value register (%rax
), %r10
, %r11
These are best used as temporaries - they might “go bad” as soon as you call a function.
.global main # any symbols (e.g., functions) that should be visible
# outside this module, need to be declared global
.text # begin the executable code segment
main: # start of the main function
enter $0, $0 # set up the call stack (more next time)
# code
# ...
# code
# ...
# code
leave # clean up the stack space
ret # return from the function
# more functions ...
.data # beginning of the data segment
# - this is where global variables are defined
format_string:
.asciz "Hello, my age is: %d\n"
some_long_integer:
.quad 42