Code Snippets
Low-Level
#Fibonacci
#NASM
#x86
Fibonacci in x86 ASM
A small assembly program that prints the next Fibonacci number after each key press.
BITS 64
default rel
global _start
; ------------------------------------------------------------
; Fibonacci sequence
; ENTER shows next number
; 'q' exits the program
; ------------------------------------------------------------
section .text
_start:
xor eax, eax ; RAX = 0
xor ebx, ebx ; RBX = 0
mov al, 1 ; Initial value: 1
fiboloop:
xchg rax, rbx ; RAX <-> RBX
add rax, rbx ; RAX = RAX + RBX (next Fibonacci number)
call print ; Print number (decimal, without newline)
call input ; Wait for input
jmp fiboloop
; ------------------------------------------------------------
; print
; Expects: RAX = unsigned number (0..2^64-1)
; Effect: Prints the number in decimal (without newline).
; Clobbers: RAX, RCX, RDX, RSI, RDI, R10, BL
; Preserves: RBX (callee-saved) is preserved
; ------------------------------------------------------------
print:
push rax ; Save Fibonacci value
push rbx ; Save RBX (callee-saved)
mov r10, rsp ; Marker: digits will be printed up to this stack state
; Special case 0 -> push '0'
test rax, rax
jnz .gen
sub rsp, 1
mov byte [rsp], '0'
jmp .emit
.gen:
; Decompose number into decimal digits (least significant digit first)
mov rcx, 10 ; Divisor 10
mov rsi, digits ; RSI = base address of digit table "0123456789"
.l1:
xor rdx, rdx ; RDX=0 because div uses (RDX:RAX)/RCX
; -> we want N/10, so high part must be 0
div rcx ; UNSIGNED division: (RDX:RAX) / RCX
; After: RAX = quotient q = floor(N/10)
; RDX = remainder r = N % 10 (0..9)
mov bl, [rsi + rdx] ; r as index into "0123456789": BL = ASCII digit
sub rsp, 1 ; reserve 1 byte on the stack
mov [rsp], bl ; push digit on stack (LSD -> MSD)
test rax, rax ; is quotient q == 0?
jnz .l1 ; if q != 0: compute next digit, else finished
.emit:
; Digits in correct order: top-of-stack -> write -> pop
.l2:
mov eax, 1 ; SYS_write
mov edi, 1 ; fd = stdout
mov rsi, rsp ; buf = &digit
mov edx, 1 ; len = 1
syscall
add rsp, 1 ; pop printed digit
cmp rsp, r10 ; all digits printed?
jne .l2
pop rbx ; restore RBX
pop rax ; restore original RAX
ret
; ------------------------------------------------------------
; input
; Effect: Reads 1 byte from stdin into usrinput.
; If 'q' was read, the program exits.
; Clobbers: RAX, RDI, RSI, RDX
; ------------------------------------------------------------
input:
push rax ; Save RAX
push rbx ; Save RBX
xor rax, rax ; RAX = 0 (SYS_read)
xor rdi, rdi ; RDI = 0 (fd = stdin)
mov rsi, usrinput ; RSI = &usrinput
mov rdx, 1 ; RDX = 1 (read 1 byte)
syscall
movzx eax, byte [usrinput] ; EAX = read byte (zero-extended)
xor al, 'q' ; AL ^ 'q' == 0 -> 'q' detected
jz exit
pop rbx ; Restore RBX
pop rax ; Restore RAX
ret
; ------------------------------------------------------------
; exit
; ------------------------------------------------------------
exit:
pop rbx ; cleanup
pop rax ; cleanup
mov eax, 60 ; SYS_exit
xor edi, edi ; Exit code 0
syscall
section .bss
usrinput resb 1 ; 1-byte input buffer
section .data
digits db "0123456789" ; Lookup table for digits