├── .gitignore ├── README.md ├── counter.s ├── fibonacci.s ├── hello.s └── mk /.gitignore: -------------------------------------------------------------------------------- 1 | *.o 2 | hello 3 | counter 4 | fibonacci 5 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Assembly Playground 2 | 3 | Random code snippets I use to learn x86_64 assembly language 4 | 5 | ## How to compile and run 6 | These are instructions for compiling and running on a Linux x86_64 machine 7 | 8 | 1) Install `nasm` using your packet manager (e.g. `pacman`, `apt`, etc.) 9 | 2) Compile object: `nasm -f elf64 -o filename.o filename.s` - `filename.s` is the input file, `filename.o` will be the generated object file 10 | 3) Link object to executable: `ld filename.o -o execname` 11 | 4) Run: `./execname` 12 | 13 | ## Files 14 | - [hello.s](hello.s) - Simple "Hello, world!" script 15 | - [counter.s](counter.s) - Counts from 0 to 9 and prints to stdout. First use of multiple calls and loops 16 | - [fibonacci.s](fibonacci.s) - Prints Fibonacci numbers from 0 to 10000. Using functions, macros and constants 17 | 18 | ## Learning resources 19 | Compared to high level languages, Assembly languages seem to have bits and pieces of knowledge very scattered around the web. I haven't found (so far) a very comprehensive learning support, but here are some helpful links I've come across: 20 | 21 | - [NASM](https://www.nasm.us/) - The most common x86_64 Assembly compiler for Linux 22 | - [NASM docs](https://www.nasm.us/doc/nasmdoc0.html) 23 | - [x86_64 registers and instructions](https://wiki.cdot.senecacollege.ca/wiki/X86_64_Register_and_Instruction_Quick_Start) 24 | - [Linux System Calls for x86_64](https://blog.rchapman.org/posts/Linux_System_Call_Table_for_x86_64/) 25 | - [Flags registers](https://en.wikipedia.org/wiki/FLAGS_register) 26 | - [NASM Assembly Programming](https://www.tutorialspoint.com/assembly_programming/index.htm) 27 | - [Kupala Assembly YT Series](https://www.youtube.com/watch?v=VQAKkuLL31g&list=PLetF-YjXm-sCH6FrTz4AQhfH6INDQvQSn) - great series of Youtube videos covering the basics 28 | - [Just Enough Assembly for Compiler Explorer](https://www.youtube.com/watch?v=soeFwz0cOqU) - another good introduction video 29 | - [NASM Assembly Tutorials](https://asmtutor.com/) 30 | -------------------------------------------------------------------------------- /counter.s: -------------------------------------------------------------------------------- 1 | ; Counts from 0 to 9 and prints the value to stdout 2 | 3 | SYS_EXIT equ 60 4 | SYS_WRITE equ 1 5 | STDOUT equ 1 6 | 7 | %macro exit 0 8 | mov rax, SYS_EXIT 9 | mov rdx, STDOUT 10 | syscall 11 | %endmacro 12 | 13 | 14 | section .data 15 | printchr dw 0 ; a value to be printed 16 | 17 | section .text 18 | global _start 19 | 20 | _start: 21 | mov r9, 0 ; counter 22 | mov r10, 9 ; maximum number of digits to print 23 | call adder 24 | exit 25 | 26 | adder: 27 | add rax, 0x30 ; transform integer to ascii character 28 | call print ; print the ascii character for the int 29 | mov rax, 10 ; set rax to the ascii value of a new line 30 | call print ; print the newline char 31 | mov rax, r9 ; move the counter value to rax 32 | add rax, 1 ; add one 33 | mov r9, rax ; update the counter variable 34 | cmp r9, r10 ; compare if it is equal or larger than the limit 35 | jle adder ; if not, re-do the adder loop 36 | ret 37 | 38 | print: 39 | mov [printchr], rax ; pass whatever is in rax to the print var 40 | mov rax, SYS_WRITE ; write syscall 41 | mov rdi, 1 42 | mov rdx, STDOUT 43 | mov rsi, printchr 44 | syscall 45 | ret 46 | -------------------------------------------------------------------------------- /fibonacci.s: -------------------------------------------------------------------------------- 1 | ;;; Prints all Fibonacci numbers from 0 to 10000 2 | 3 | ; CONSTANTS 4 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 5 | SYS_WRITE equ 1 6 | SYS_EXIT equ 60 7 | STDIN equ 0 8 | STDOUT equ 1 9 | STDERR equ 2 10 | 11 | ; MACROS 12 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 13 | %macro exit 0 14 | mov rax, SYS_EXIT 15 | mov rdi, STDIN 16 | syscall 17 | %endmacro 18 | 19 | %macro printInt 1 20 | mov bx, %1 21 | add bx, 0x30 22 | mov [printstr], bx 23 | mov rax, SYS_WRITE 24 | mov rdi, STDOUT 25 | mov rdx, 1 26 | mov rsi, printstr 27 | syscall 28 | %endmacro 29 | 30 | %macro printnl 0 31 | mov bx, 10 32 | mov [printstr], bx 33 | mov rax, SYS_WRITE 34 | mov rdi, STDOUT 35 | mov rdx, 1 36 | mov rsi, printstr 37 | syscall 38 | %endmacro 39 | 40 | %macro increment_buffer 0 41 | mov dx, [buffersize] 42 | add dx, 1 43 | mov [buffersize], dx ; increment the buffer size 44 | %endmacro 45 | 46 | ; SECTIONS 47 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 48 | section .data 49 | printstr dw 0 50 | buffersize dw 0 51 | quotient dw 0 52 | 53 | section .text 54 | global _start 55 | 56 | ; FUNCTIONS 57 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 58 | _start: 59 | mov r9w, 0 ; initialize number n1 60 | mov r10w, 1 ; initialize number n2 61 | call _main 62 | exit 63 | 64 | _main: 65 | mov [quotient], r10w 66 | call _parseint 67 | call _fibo 68 | cmp r10w, 10_000 69 | jle _main 70 | ret 71 | 72 | _fibo: 73 | push r10w ; save value of n2 74 | add r10w, r9w ; update n2 (n1+n2) 75 | pop r9w ; pass old value of n2 to n1 76 | ret 77 | 78 | _parseint: 79 | mov ax, [quotient] 80 | mov dx, 0 81 | mov bx, 10 82 | div bx ; divide the integer by 10 83 | push dx ; push remainder to the stack 84 | increment_buffer 85 | 86 | mov [quotient], ax ; update quotient 87 | cmp ax, 10 ; is the quotient still larger than 10? 88 | jge _parseint ; if yes, keep parsing remainders 89 | 90 | cmp ax, 0 ; is it zero? 91 | je _print_buffer ; if yes, print the buffer 92 | 93 | push ax ; if not, add the quotient to the stack 94 | increment_buffer 95 | jmp _print_buffer ; and print the buffer 96 | 97 | _print_buffer: 98 | pop ax 99 | printInt ax 100 | mov bx, [buffersize] 101 | sub bx, 1 102 | mov [buffersize], bx 103 | cmp bx, 0 104 | jg _print_buffer 105 | printnl 106 | ret 107 | -------------------------------------------------------------------------------- /hello.s: -------------------------------------------------------------------------------- 1 | ; Resources: 2 | ; https://www.nasm.us/ 3 | ; http://heather.cs.ucdavis.edu/~matloff/50/LinuxAssembly.html#tth_sEc3 4 | ; http://www.cs.fsu.edu/~langley/CNT5605/2019-Summer/assembly-example/assembly.html 5 | ; https://blog.rchapman.org/posts/Linux_System_Call_Table_for_x86_64/ 6 | ; https://en.wikipedia.org/wiki/Write_(system_call) 7 | 8 | global _start 9 | 10 | section .data 11 | hello_world db 'Hello, world!',10 ;string and the ascii code for a new line (10) 12 | 13 | section .text 14 | _start: 15 | mov rax, 1 ;1 is the syscall code for write. bellow the arguments are set 16 | mov rdi, 1 ;fd - 0: stdin, 1:stdou, 2:sterr 17 | mov rsi, hello_world ;buffer: char array to be written to the file pointed by fd 18 | mov rdx, 14 ;length: how many bytes of the buffer to write to fd 19 | syscall ;runs the syscall set above on %rax 20 | 21 | mov rax, 60 ;60 is the syscall code to Sys_exit. %rdi sets the error code 22 | mov rdi, 0 ;error code set to 0 23 | syscall 24 | -------------------------------------------------------------------------------- /mk: -------------------------------------------------------------------------------- 1 | #!/usr/bin/sh 2 | ##### 3 | # compiles and runs a NASM script 4 | # input: NASM file with .s extension 5 | ##### 6 | filestem=`echo $1 | cut -d'.' -f1` 7 | 8 | nasm -f elf64 $filestem\.s -o $filestem\.o & 9 | ld $filestem\.o -o $filestem 10 | ./$filestem 11 | 12 | exit 0 13 | --------------------------------------------------------------------------------