89 lines
2.7 KiB
Plaintext
89 lines
2.7 KiB
Plaintext
; Calculates and prints Fibonacci numbers (Fn)
|
|
; Prints numbers 1 - 47 (largest 32bit Fn that fits)
|
|
; Build:
|
|
; nasm -felf32 fib.asm
|
|
; ld -m elf32_i386 fib.o -o fib
|
|
|
|
global _start
|
|
section .text
|
|
|
|
_start:
|
|
mov ecx, 48 ; Initialize loop counter
|
|
.loop:
|
|
mov ebx, 48 ; Calculate which Fn will be computed
|
|
sub ebx, ecx ; Takes into account the reversed nature
|
|
push ebx ; Pass the parameter in on the stack
|
|
push .done ; Emulate a call but "return" to end of loop
|
|
; The return adress is manually set on the stack
|
|
; int fib (int n)
|
|
; Returns the n'th Fn
|
|
; fib(n) = 0 if n <= 0
|
|
; 1 if n == 1
|
|
; fib(n-1) + fib(n-2) otherwise
|
|
.fib:
|
|
push ebp ; Setup stack frame
|
|
mov ebp, esp
|
|
push ebx ; Save needed registers
|
|
|
|
xor eax, eax
|
|
mov ebx, [ebp + 8] ; Get the parameter
|
|
cmp ebx, 1 ; Test for base cases
|
|
jl .return
|
|
mov eax, 1
|
|
je .return
|
|
dec ebx ; Calculate fib(n-1)
|
|
push ebx
|
|
call .fib
|
|
mov [esp], eax ; Save result on top of parameter in stack
|
|
dec ebx ; Calculate fib(n-2)
|
|
push ebx
|
|
call .fib
|
|
add eax, [esp + 4] ; Add the first to the second
|
|
add esp, 8 ; Reset local stack
|
|
.return:
|
|
pop ebx ; Restore modified registers
|
|
mov esp, ebp ; Tear down stack frame and return
|
|
pop ebp
|
|
ret
|
|
.done:
|
|
mov [esp], ecx ; Save the counter between calls
|
|
push eax ; Print the number
|
|
call print_num
|
|
add esp, 4
|
|
pop ecx ; Restore the loop counter
|
|
loop .loop ; Loop until 0
|
|
|
|
mov eax, 0x01 ; sys_exit(int error)
|
|
xor ebx, ebx ; error = 0 (success)
|
|
int 0x80 ; syscall
|
|
|
|
; void print_num (int n)
|
|
; Prints an integer and newline
|
|
print_num:
|
|
push ebp
|
|
mov ebp, esp
|
|
sub esp, 11 ; Save space for digits and newline
|
|
|
|
lea ecx, [ebp - 1] ; Save a pointer to after the buffer
|
|
mov BYTE [ecx], 0x0A ; Set the newline at the end
|
|
mov eax, [ebp + 8] ; Get the parameter
|
|
mov ebx, DWORD 10 ; Divisor
|
|
.loop:
|
|
dec ecx ; Move pointer to next digit
|
|
xor edx, edx
|
|
div ebx ; Extract one digit, quot in eax, rem in edx
|
|
add dl, 0x30 ; Convert remainder to ascii
|
|
mov [ecx], dl ; Save the ascii form
|
|
cmp eax, 0 ; Loop until all digits have been converted
|
|
jg .loop
|
|
|
|
mov eax, 0x04 ; sys_write(int fd, char **buf, int len)
|
|
mov ebx, 1 ; stdout
|
|
mov edx, ebp ; Calculate the length
|
|
sub edx, ecx ; address after newline - address of first digit
|
|
int 0x80
|
|
|
|
mov esp, ebp
|
|
pop ebp
|
|
ret
|