Introduction
In RISC-V assembly, .section is an assembler directive used to
divide your program into different parts—such as executable code,
initialized data, or uninitialized variables—telling the assembler
and linker how to organize the memory layout.
An assembly file is not just a single continuous block of
instructions. Different parts of a program have different
hardware and permission requirements (for example, code can
be executed, but variables need to be read from or written to).
The .section directive changes the current output section in
the object file.
Some Common Section Are
Assemblers and linkers recognize several standard section names:
- .text: The code section. It contains the actual executable
machine instructions (like add, lw, jal). This area is typically
marked as read-only and executable by the operating system or
hardware.
- .data: The initialized data section. It stores global or
static variables that have pre-assigned values when the program
starts (such as strings or constant arrays).
- .bss: The uninitialized data section. It reserves space for
global or static variables that are initialized to zero at runtime.
These do not take up space in the stored binary file, saving
storage footprint.
- .rodata: The read-only data section. It holds constant values
or strings that cannot be modified while the program runs.
Code Example From The Web
Slightly modified by me.
# ---------------------------------------------------------------------
# 1. DATA SECTION: Variables initialized with values
# ---------------------------------------------------------------------
.data
.align 2 # Align data to 4-byte boundary (22)
greeting: .asciz "Hello, RISC-V!\n" # Null-terminated string
my_number: .word 42 # A 32-bit integer
# ---------------------------------------------------------------------
# 2. BSS SECTION: Variables allocated, but not given a hardcoded value
# ---------------------------------------------------------------------
.bss
.align 2 # Align data to 4-byte boundary (22)
user_buffer: .space 64 # Reserve 64 bytes for runtime input
# ---------------------------------------------------------------------
# 3. TEXT SECTION: Executable program code
# ---------------------------------------------------------------------
.text
.global main # Expose entry point to the linker
main:
# Loading the address of our variable into register a0
la a0, greeting
# .........................................................
# ... your logic, system calls, or processing loop here ...
# .........................................................
# Exit program via Linux syscall 93
li a7, 93 # Syscall number for exit
li a0, 0 # Return code 0
ecall # Trigger environment call
Best Practices
Memory Alignment: Always use .align (or .p2align) directives
before declaring variables in your .data or .bss sections.
RISC-V memory transfers generally require data to be aligned with
the register sizes to prevent alignment faults or severe performance
drops.
Logical Flow: You can switch back and forth between sections
as much as you want in a single file. The assembler automatically
gathers all pieces belonging to the same section and joins them
together.