We will be working with numbers quite a bit and in different roles: counting, addresses, offsets, switches, etc.
For simplicity, we will (mostly) avoid floating point and talk about integers
In majority of cultures (feel free to let me know if I’m wrong), we humans use the decimal system
Computers understand binary: everything is either 0 or 1 (off or on)
Also a positional system, but only 2 digits: 0 and 1
Example: 1111012
Any binary number is broken down into digits similarly to decimal, but the base is 2: an × 2n + an − 1 × 2n − 1 + an − 2 × 2n − 2 + ... + a0 × 20
Binary: easy for computer, but impractical
Solution? converting between decimal and binary? Too cumbersome
Solution! Use bases that are easier to convert: octal or hexadecimal
Octal: 8 digits - 0-7
For example 3718
Most useful for us: hexadecimal
Digits: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, A, B, C, D, E, F (can be also lower case)
Because 16 = 24, each digit corresponds to 4 binary digits so they map nicely
E.g., 88E5 = 1000100011100101
1 0 0 0 1 0 0 0 1 1 1 0 0 1 0 1
8+0+0+0 8+0+0+0 8+4+2+0 0+4+0+1
8 8 E 5
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
add
, sub
, imul
,
idiv
, and
, or
, xor
,
etc.mov
and perform the
operation on the two operands and store the result in the
Destination
OP
:
Destination = Destination OP Source
asm addq $3, %rax imul %rax, %rbx
28 - (10 + 3) * 2
- translate to assembly
Can only do one operation at a time
Use BODMAS (Brackets, Orders, Division & Multiplication, Addition & Subtraction)
Compute (10+3) first:
movq $10, %rax
movq $3, %rbx # optional, could just do addq $3, %rax
%rbx, %rax # result will be in rax addq
Multiply by 2
$2, %rax imulq
Subtract from 28
movq $28, %rbx
%rax, %rbx subq
Result is now in rbx
inc
,
dec
, neg
, not
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
Note: In practice, we will also reverse the condition we jump in - we’ll talk about this in the next lecture
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 |
printf
, fprintf
, scanf
, etc.printf
, fprintf
, etc., are
special: they take variable numbers of argumentsprintf
: it takes at least a format
string, which can be followed by additional arguments – depending
on how many format specifiers are in the format stringman 3 printf
%al
needs to be set to
0
, e.g., using mov $0, %al
%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