Excercise Script

We are going to make a Fibonacci calculator. Fibonacci is simpley 1 + 1 = 2, then take last numbers and add to 1 + 2 = 3. The program will take an input of max number.
We start with data movement by setting 0 to rax
and 1 to rxb
.
global _start ; Tell assembler to make entry point _start visible to linker.
section .text ; .text is where code and instructions go.
_start:
mov rax, 0 ; Put 0 value into rax
mov rbx, 1 ; Put 1 value into rbx
As 1 would be 0x00000001 in 64 bit, its not efficient so we use 1 byte register bl
.
global _start
section .text
_start:
mov al, 0
mov bl, 1
Address Pointers
Pointer registers do not contain values but the point to another address that holds the value. For example if we would mov rax, rsp
as rsp is the current stack pointer. We are not moving the value but move the pointer address to rax
.
Loading Value Pointers
Using lea
or Load Effective Address we load a pointer to a specific value like: lea rax, [rsp]
. This is the opposite from above where we load pointer to a value and here we move value from pointer, it loads the address not the value.
global _start
section .text
_start:
lea rax, [rsp+10]
mov rax, [rsp+10]
Arithmetic Instructions
Assuming rax starts at 1 for each instruction.
inc
Increment by 1
inc rax
-> rax++
or rax += 1
-> rax = 2
dec
Decrement by 1
dec rax
-> rax--
or rax -= 1
-> rax = 0
Now lets increment the value of bl
with 1.
global _start
section .text
_start:
mov al, 0 ; al more efficent than rax, set value 0
mov bl, 0 ; set value at 0
inc bl ; increment with 1
Binary Instructions
add
Add both operands
add rax, rbx
-> rax = 1 + 1
-> 2
sub
Subtract Source from Destination (i.e rax = rax - rbx
)
sub rax, rbx
-> rax = 1 - 1
-> 0
imul
Multiply both operands
imul rax, rbx
-> rax = 1 * 1
-> 1
global _start
section .text
_start:
mov al, 0
mov bl, 0
inc bl ; we increment with 1
add rax, rbx ; rax is equal to 0x1 + 0x0. rax = rax + rbx
Bitwise Intstructions
not
Bitwise NOT (invert all bits, 0->1 and 1->0)
not rax
-> NOT 00000001
-> 11111110
and
Bitwise AND (if both bits are 1 -> 1, if bits are different -> 0)
and rax, rbx
-> 00000001 AND 00000010
-> 00000000
or
Bitwise OR (if either bit is 1 -> 1, if both are 0 -> 0)
or rax, rbx
-> 00000001 OR 00000010
-> 00000011
xor
Bitwise XOR (if bits are the same -> 0, if bits are different -> 1)
xor rax, rbx
-> 00000001 XOR 00000010
-> 00000011
We can uss xor
to torn any value to 0 by xor
ing a value with itself. So if rax
would 8888, you xor
it with itself which is 8888 and thus is 0.
global _start
section .text
_start:
xor rax, rax ; better than mov al, 0
xor rbx, rbx ; better than mov bl, 0
inc rbx
add rax, rbx
Loop Structure
mov rcx, x
Sets loop (rcx
) counter to x
mov rcx, 3
loop
Jumps back to the start of loop
until counter reaches 0
loop exampleLoop
global _start
section .text
_start:
xor rax, rax ; initialize rax to 0
xor rbx, rbx ; initialize rbx to 0
inc rbx ; increment rbx to 1
mov rcx, 10 ; 10 iterations
loopFib:
add rax, rbx ; get the next number
xchg rax, rbx ; swap values
loop loopFib
Unconditional Branching
jump
will allow us to jump
to any point in the program if a condition is met. After that it will continue processing instructions from that point. The basic jmp
will always jump to the specified location, regardless of conditions.
Conditional Branching
Conditional Branching instructions are only processed when a specific condition is meet.
jz D = 0 ; Destination equal to Zero
jnz D != 0 ; Destination Not equal to Zero
For all conditions: https://www.intel.com/content/dam/www/public/us/en/documents/manuals/64-ia-32-architectures-software-developer-instruction-set-reference-manual-325383.pdf#page=585
CMP
The compare instruction compares 2 operands, by subtracting the 2nd operand from the first. So after the first Fibonacci number is calculated it will 1 - 10 = -9 and as its negative it will jump, once it hits positve number it will not jump.
global _start
section .text
_start:
xor rax, rax ; initialize rax to 0
xor rbx, rbx ; initialize rbx to 0
inc rbx ; increment rbx to 1
loopFib:
add rax, rbx ; get the next number
xchg rax, rbx ; swap values
cmp rbx, 10 ; do rbx - 10
js loopFib ; jump if result is <0
PUSH/POP
To preserve our registers and values we can push
it to the stack and get them back after syscall using pop
.
global _start
section .text
_start:
xor rax, rax ; initialize rax to 0
xor rbx, rbx ; initialize rbx to 0
inc rbx ; increment rbx to 1
push rax ; push registers to stack
push rbx
; call function
pop rbx ; restore registers from stack
pop rax
Syscalls
Syscall is function written in C, like read or write. The write
syscall has number 1 so mov rax, 1
. However write requires arguments.
rdi
->1
(for stdout)rsi
->'Fibonacci Sequence:\n'
(pointer to our string)rdx
->20
(length of our string)
As the string is longer than 16 chars - 64 bits we need a variable. Message label is the pointer to where our strings is stored in memory. Below will not work yet.
global _start
section .data
message db "Fibonacci Sequence:", 0x0a
mov rax, 1 ; rax: syscall number 1
mov rdi, 1 ; rdi: fd 1 for stdout
mov rsi,message ; rsi: pointer to message
mov rdx, 20 ; rdx: print length of 20 bytes
syscall ; call write syscall intro message
xor rbx, rbx ; initialize rbx to 0
inc rbx ; increment rbx to 1
loopFib:
add rax, rbx ; get the next number
xchg rax, rbx ; swap values
cmp rbx, 10 ; do rbx - 10
js loopFib ; jump if result is <0
mov rax, 60
mov rdi, 0
syscall
Procedures
A procedure
(sometimes referred to as a subroutine
) is usually a set of instructions we want to execute at specific points in the program. Using ret
we return to the point where we were before jumping tot the procedure.
call
push the next instruction pointer rip
to the stack, then jumps to the specified procedure
call printMessage
ret
pop the address at rsp
into rip
, then jump to it
ret
global _start
section .data
message db "Fibonacci Sequence:", 0x0a
section .text
_start:
call printMessage ; print intro message
call initFib ; set initial Fib values
call loopFib ; calculate Fib numbers
call Exit ; Exit the program
printMessage:
mov rax, 1 ; rax: syscall number 1
mov rdi, 1 ; rdi: fd 1 for stdout
mov rsi,message ; rsi: pointer to message
mov rdx, 20 ; rdx: print length of 20 bytes
syscall ; call write syscall to the intro message
ret
initFib:
xor rax, rax ; initialize rax to 0
xor rbx, rbx ; initialize rbx to 0
inc rbx ; increment rbx to 1
ret
loopFib:
add rax, rbx ; get the next number
xchg rax, rbx ; swap values
cmp rbx, 10 ; do rbx - 10
js loopFib ; jump if result is <0
ret
Exit:
mov rax, 60 ; 60 is syscall nr for exit
mov rdi, 0
syscall
Last updated
Was this helpful?