YouTip LogoYouTip

Assembly Procedure

Assembly Language - Procedures (Subroutines)

Assembly Language - Procedures (Subroutines)

A Procedure is a mechanism in assembly language for implementing reusable functions/subroutines, enabling structured and reusable code. Understanding the relationship between procedures and the stack is a significant milestone in assembly programming.


What Is a Procedure?

A procedure is a block of code that can be called multiple times, similar to a function or subroutine in high-level languages.

In assembly, procedures are invoked using the CALL instruction and returned from using the RET instruction. CALL pushes the return address onto the stack, and RET pops the return address from the stack and jumps back to it.

Example

; File path: simple_proc.asm

; Simplest procedure call example

section .data

 msg db 'Hello, tutorial!', 0xA

 len equ $ - msg

section .text

global _start

_start:

 call print_message ; Call procedure (pushes address of next instruction onto stack)

 call print_message ; Call again

 mov eax, 1

 mov ebx, 0

 int 0x80

; Procedure: print message

print_message:

 push eax ; Save registers to be modified

 push ebx

 push ecx

 push edx

 mov eax, 4

 mov ebx, 1

 mov ecx, msg

 mov edx, len

 int 0x80

 pop edx ; Restore registers (in reverse order)

 pop ecx

 pop ebx

 pop eax

 ret ; Return to caller (pop return address from stack)
In a procedure, you must save and restore all registers that are modified (except EAX when it is used as a return value). This is basic etiquette in assembly programming. Failing to do so may unintentionally modify the caller’s register values.

How CALL and RET Work

CALL and RET work in pairs and rely on the stack to manage return addresses:

Instruction Actual Operation
CALL label push eip (save address of next instruction) + jmp label
RET pop eip (pop address from stack and jump)

Passing Parameters via Registers

Place parameters into predefined registers before calling the procedure:

Example

; File path: proc_params_reg.asm

; Pass parameters via registers

section .data

 newline db 0xA

section .text

global _start

_start:

 ; Call add_two procedure: compute 10 + 20

 mov eax, 10 ; First parameter in eax

 mov ebx, 20 ; Second parameter in ebx

 call add_two ; Call procedure

 ; Return value in eax = 30

 mov ebx, eax ; Exit code = 30

 mov eax, 1

 int 0x80

; Procedure: compute eax + ebx, result returned in eax

add_two:

 add eax, ebx ; eax = eax + ebx

 ret

Passing Parameters via Stack

Stack-based parameter passing is more flexible and is the standard approach used by high-level languages like C:

Example

; File path: proc_params_stack.asm

; Pass parameters via stack (cdecl style)

section .data

 msg db 'Sum is: '

 msg_len equ $ - msg

 newline db 0xA

section .bss

 result_buf resb 4

section .text

global _start

_start:

 ; Call sum procedure: compute 100 + 200

 push dword 200 ; Push 2nd parameter

 push dword 100 ; Push 1st parameter

 call sum ; Call procedure

 add esp, 8 ; β˜… Caller cleans up stack (cdecl convention)

 ; Return value in eax = 300

 mov ebx, eax

 mov eax, 1

 int 0x80

; Procedure: sum(a, b) = a + b

sum:

 push ebp ; β˜… Save old base pointer

 mov ebp, esp ; β˜… Set new stack frame base

 ; Stack layout (high to low addresses):

 ; [ebp+12] = parameter b (200)

 ; [ebp+8] = parameter a (100)

 ; [ebp+4] = return address

 ;  = old ebp

 ;  = local variable space

 mov eax, [ebp+8] ; Get 1st parameter (a)

 add eax, [ebp+12] ; Add 2nd parameter (b)

 pop ebp ; β˜… Restore old base pointer

 ret ; Return

Stack frame structure diagram:

Image 1: Stack Frame Structure

Textual illustration:

High Address
+------------------+
| Parameter2 (200) | <-- [ebp + 12]
+------------------+
| Parameter1 (100) | <-- [ebp + 8]
+------------------+
| Return Address   | <-- [ebp + 4]
+------------------+
| Old EBP          | <--  (current EBP points here)
+------------------+
| Local Variables  | <-- , , ...
+------------------+
Low Address          <-- ESP points here
The prologue (push ebp; mov ebp, esp) and epilogue (pop ebp; ret or leave; ret) form the standard stack frame management template. Almost all assembly functions begin and end with this structure.

Procedure Return Values

Return values are typically stored in the EAX register (for 32-bit values) or EDX:EAX (for 64-bit values):

Example

; Return value examples

; Return int

 call get_answer

 ; eax = 42

; Return 64-bit value (e.g., long long)

 call get_big_value

 ; edx:eax = 64-bit result

get_answer:

 mov eax, 42 ; Return value placed in eax

 ret

get_big_value:

 mov eax, 0x00000001 ; Low 32 bits

 mov edx, 0x00000000 ; High 32 bits

 ret

Local Variables

Local variables use stack space and are allocated in the procedure prologue by decreasing ESP:

Example

; File path: local_vars.asm

; Use local variables in a procedure

section .text

global _start

_start:

 push dword 10

 push dword 20

 call multiply_add

 add esp, 8

 ; eax = 10 * 20 + 10 + 20 = 230

 mov ebx, eax

 mov eax, 1

 int 0x80

; Procedure: multiply_add(x, y) = x*y + x + y

multiply_add:

 push ebp

 mov ebp, esp

 sub esp, 8 ; β˜… Allocate 8-byte local variable space on stack

 ; Now  and  are available as local variables

 mov eax, [ebp+8] ; x

 mov ebx, [ebp+12] ; y

 ;  = x * y

 imul eax, ebx

 mov , eax ; Local variable 1 = x * y

 ;  = x + y

 mov eax, [ebp+8]

 add eax, [ebp+12]

 mov , eax ; Local variable 2 = x + y

 ; Return value =  + 

 mov eax, 

 add eax, 

 ; β˜… Clean up local variable space and restore

 mov esp, ebp ; Equivalent to add esp, 8

 pop ebp

 ret
Local variables are allocated in the stack frame and automatically released upon procedure return. The leave instruction can be used instead of mov esp, ebp; pop ebp, with equivalent effect.

Comparison of Calling Conventions

Convention Parameter Passing Stack Cleaner Register Preservation Return Value
cdecl Stack (pushed right-to-left) Caller EAX, ECX, EDX preserved by caller EAX
stdcall Stack (pushed right-to-left) Callee EAX, ECX, EDX preserved by caller EAX
fastcall ECX, EDX + stack Callee EAX, ECX, EDX preserved by caller EAX
← Assembly MacroAssembly String β†’