Subroutines in Assembly

Vishal Rashmika published on
2 min, 302 words

Categories: Assembly

x86 assembly unlocks the raw power of your processor. But complex programs need a way to break down tasks into manageable chunks. That's where subroutines come in, also known as procedures or functions in other high level languages. They introduce modularity, making your code cleaner, reusable, and easier to maintain.

In this post, we'll dive into the world of subroutines in NASM for 64-bit architectures.

Why Subroutines?

Imagine writing the same block of code ten times. Yuck! Subroutines let you define a task once and call it whenever needed. This keeps your code concise and eliminates redundancy. They also promote better organization, making complex programs easier to understand and navigate. Debugging becomes a breeze, as you can focus on isolated sections of code.

Building a Subroutine

Let's write a subroutine that prints a message to the console. Here's a basic structure:

section .data
	message db "GoodBye!",10

print_salutation:
	mov rax,1
	mov rdi,1
	mov rsi, message
	mov rdx, 9
	syscall ;calling the system call for printing
	ret ;return from the subroutine

Calling the Subroutine

Now, let's call our print_message subroutine from our main program:

; ... 
call print_salutation ; Calling the subroutine
; ... (more main program code)

The call instruction jumps to the subroutine's starting address. When the subroutine finishes (using ret), control returns to the instruction after the call.

Full Program

section .data
	text db "Hello, World!",10
	message db "GoodBye!",10

section .text
	global _start

_start:
	mov rax, 1
	mov rdi, 1
	mov rsi, text
	mov rdx, 14
	syscall
	
	call print_salutation
	jmp print_exit

print_salutation:
	mov rax,1
	mov rdi,1
	mov rsi, message
	mov rdx, 9
	syscall
	ret

print_exit:	
	mov rax, 60
	mov rdi, 0
	syscall

Remember: This is a simplified overview. For detailed instruction explanations and advanced topics, refer to the NASM documentation and online resources. Happy hacking!