Concept and Function of Macros
Macros are an important tool in assembly language for achieving code reuse and modular programming. They allow programmers to define a reusable code template that generates repeated code sequences in a program through simple macro calls.
Syntax for Defining Macros
In the NASM assembler, macros are defined using<span>%macro</span> and <span>%endmacro</span> directives:
%macro macro_name number_of_parameters
; Macro body - contains the sequence of instructions to be reused
%endmacro
- Macro Name: The unique name that identifies the macro
- Number of Parameters: The number of parameters the macro accepts
- Macro Body: Contains the actual assembly instructions
Basic Macro Examples
1. Simple String Output Macro
section .data
hello db 'Hello, World!', 0xA
hello_len equ $ - hello
message db 'Welcome to Assembly Programming', 0xA
msg_len equ $ - message
section .text
global _start
; Define a macro to output a string
%macro PRINT_STRING 2
mov eax, 4 ; sys_write system call
mov ebx, 1 ; standard output
mov ecx, %1 ; string address (first parameter)
mov edx, %2 ; string length (second parameter)
int 0x80
%endmacro
_start:
PRINT_STRING hello, hello_len ; Call the macro
PRINT_STRING message, msg_len ; Call the macro again
mov eax, 1 ; sys_exit
mov ebx, 0
int 0x80
2. General Output Macro with Register Preservation
; More sophisticated output macro that automatically saves and restores registers
%macro SAFE_PRINT 2
push eax ; Save registers
push ebx
push ecx
push edx
mov eax, 4 ; sys_write
mov ebx, 1 ; stdout
mov ecx, %1 ; string address
mov edx, %2 ; string length
int 0x80
pop edx ; Restore registers
pop ecx
pop ebx
pop eax
%endmacro
Advanced Macro Features
1. Multi-Parameter Macros
; Macro that supports multiple parameters
%macro MULTI_OPERATION 4
mov eax, %1 ; First operand
mov ebx, %2 ; Second operand
%3 ; Operation (e.g., add, sub, etc.)
mov %4, eax ; Result storage location
%endmacro
section .data
result dd 0
section .text
_start:
; Use the macro for addition
MULTI_OPERATION 10, 20, add eax, ebx, [result]
; Use the macro for multiplication
MULTI_OPERATION 5, 6, imul eax, ebx, [result]
2. Conditional Macros
; Macro with conditional checks
%macro CONDITIONAL_PRINT 3
cmp %1, %2 ; Compare two values
j%-3 .skip_%$ ; Conditional jump (%3 is the condition like ne, e, g, etc.)
SAFE_PRINT msg_equals, msg_equals_len
.skip_%$:
%endmacro
section .data
msg_equals db 'Values are equal', 0xA
msg_equals_len equ $ - msg_equals
3. Recursive Macros
; Recursive macro example - calculating power
%macro POWER 3
%if %2 = 0
mov %3, 1 ; Any number to the power of 0 is 1
%elif %2 = 1
mov %3, %1 ; Any number to the power of 1 is itself
%else
; Recursively calculate power(base, exponent-1)
POWER %1, %2-1, %3
mov eax, %3
imul eax, %1 ; Multiply by base
mov %3, eax
%endif
%endmacro
Complete Macro Application Example
section .data
; Various message definitions
title_msg db '=== Assembly Macro Demonstration ===', 0xA, 0xA, 0
title_len equ $ - title_msg
add_msg db 'Addition Result: ', 0
add_len equ $ - add_msg
sub_msg db 'Subtraction Result: ', 0
sub_len equ $ - sub_msg
mul_msg db 'Multiplication Result: ', 0
mul_len equ $ - mul_msg
newline db 0xA, 0
space db ' ', 0
section .bss
buffer resb 10 ; Number conversion buffer
section .text
global _start
; =============================================
; Macro Definition Area
; =============================================
; Safe string output macro
%macro PRINT 1
pusha ; Save all registers
mov esi, %1 ; String address
call strlen ; Calculate string length
mov edx, ecx ; Length
mov ecx, %1 ; String address
mov ebx, 1 ; stdout
mov eax, 4 ; sys_write
int 0x80
popa ; Restore all registers
%endmacro
; Arithmetic operation macro with labels
%macro ARITHMETIC_OPERATION 4
pusha
PRINT %1 ; Output operation description
mov eax, %2 ; First operand
mov ebx, %3 ; Second operand
%4 ; Operation instruction
call print_number ; Output result
PRINT newline
popa
%endmacro
; Exit program macro
%macro EXIT 1
mov eax, 1 ; sys_exit
mov ebx, %1 ; Exit code
int 0x80
%endmacro
; =============================================
; Main Program
; =============================================
_start:
PRINT title_msg
; Demonstrate various arithmetic operations
ARITHMETIC_OPERATION add_msg, 15, 7, add eax, ebx
ARITHMETIC_OPERATION sub_msg, 20, 8, sub eax, ebx
ARITHMETIC_OPERATION mul_msg, 6, 9, imul eax, ebx
EXIT 0
; =============================================
; Subroutine Area
; =============================================
; Calculate string length
; Input: ESI = string address
; Output: ECX = string length
strlen:
push esi
mov ecx, 0
.count_loop:
cmp byte [esi], 0
je .done
inc esi
inc ecx
jmp .count_loop
.done:
pop esi
ret
; Output number
; Input: EAX = number to output
print_number:
pusha
mov edi, buffer ; Buffer address
mov ecx, 0 ; Digit count
mov ebx, 10 ; Divisor
; Handle special case for number 0
cmp eax, 0
jne .convert
mov byte [edi], '0'
inc edi
mov byte [edi], 0
jmp .print
.convert:
; Number to string (reverse)
.convert_loop:
mov edx, 0
div ebx ; EAX = quotient, EDX = remainder
add dl, '0' ; Number to ASCII
push dx ; Save to stack
inc ecx
cmp eax, 0
jne .convert_loop
; Retrieve number from stack (in order)
.pop_loop:
pop ax
mov [edi], al
inc edi
loop .pop_loop
mov byte [edi], 0 ; String terminator
.print:
; Output number
mov esi, buffer
call strlen
mov edx, ecx
mov ecx, buffer
mov ebx, 1
mov eax, 4
int 0x80
popa
ret
Special Functions and Advanced Uses of Macros
1. Default Parameters
; Macro with default parameters
%macro CONFIGURABLE_PRINT 1-3 1, 0
; %1 = string address (required)
; %2 = file descriptor (optional, default 1=stdout)
; %3 = newline (optional, default 0=no newline)
pusha
mov esi, %1
call strlen
mov edx, ecx
mov ecx, %1
mov ebx, %2
mov eax, 4
int 0x80
%if %3 = 1
mov ecx, newline
mov edx, 1
mov ebx, %2
mov eax, 4
int 0x80
%endif
popa
%endmacro
2. Variable Argument Macros
; Variable argument macro
%macro VARIABLE_ARGS 1-*
; %1 = first parameter
; %0 = total number of parameters
%rep %0
push %1
%rotate 1
%endrep
%endmacro
3. Local Labels
; Using local labels to avoid conflicts
%macro SAFE_LOOP 2
%%loop_start: ; Local label
; Loop body
dec %1
jnz %%loop_start
%endmacro
Advantages and Disadvantages of Macros
Advantages:
- Code Reuse: Avoid rewriting the same code
- Readability: Improve code readability with meaningful macro names
- Maintainability: Modifying the macro definition affects all calls
- Level of Abstraction: Hide underlying implementation details
Disadvantages:
- Debugging Difficulty: Code after macro expansion may be hard to debug
- Code Bloat: Multiple calls may generate a lot of duplicate code
- Complexity: Complex macros may be hard to understand and maintain
Best Practices
- Naming Conventions: Use uppercase letters and underscores for macro names
- Documentation Comments: Add detailed comments for complex macros
- Parameter Validation: Include necessary parameter checks within macros
- Register Protection: Properly save and restore registers within macros
- Moderate Use: Avoid excessive use of macros that make code hard to understand
By using macros appropriately, the readability, maintainability, and development efficiency of assembly code can be significantly improved, making it an important technique in modern assembly programming.