Assembly Language - Memory Segmentation
Memory Segmentation is a core concept in the x86 architecture, determining how a program organizes code, data, and stack space in memory.
Why Segmentation is Needed
In x86 real mode, the CPU uses 16-bit registers, but it needs to access 1MB of memory space (20-bit addresses).
A 16-bit register can only represent a 64KB range (2^16 = 65536), which is far from enough.
Intel's solution is to divide memory intosegments (Segment), each segment has a base address and an offset, and throughsegment address + offset, the complete physical address is formed.
Physical address calculation formula:
物理地址 = 段地址 × 16 + 偏移地址
Although in protected mode (32-bit), the segmentation mechanism is more used for memory protection and permission control, understanding segmentation is still crucial to understanding the structure of assembly programs.
Three Basic Segments
A typical assembly program uses three main segments:
| Segment Name | English Name | Purpose | Corresponding Section |
|---|---|---|---|
| Code Segment | Code Segment | Stores executable machine instructions | section .text |
| Data Segment | Data Segment | Stores initialized global variables | section .data |
| Stack Segment | Stack Segment | Stores function call information and local variables | Automatically managed by the operating system |
Code Segment (.text)
The code segment stores all machine instructions of the program and is aread-only, executablememory region.
When loading a program, the operating system maps the code segment to read-only memory pages to prevent the program from accidentally modifying instructions.
Example
; Demonstrates the use of the code segment
section .text ; Start of code segment
global _start
_start:
mov eax, 1 ; These instructions are all stored in the code segment
mov ebx, 0
int 0x80
; The following is a helper function, also stored in the code segment
my_function:
mov eax, 42
ret
Data Segment (.data)
The data segment storesthe program's initialized global variables。
The data segment is readable and writable, and its contents can be modified during program execution.
Example
; Demonstrates the use of the data segment
section .data
; Define initialized variables of various types
msg db 'Hello, example!', 0 ; String variable (byte sequence)
count db 100 ; Byte variable, initial value 100
pi dd 314159 ; Double-word variable, storing approximation of π × 100000
array db 1, 2, 3, 4, 5 ; Byte array
section .text
global _start
_start:
; Read variables from the data segment
mov al, [count] ; Load the value of count (100) into the al register
; ...
mov eax, 1
mov ebx, 0
int 0x80
BSS Segment (.bss)
The BSS (Block Started by Symbol) segment storesuninitialized global variables。
Unlike the data segment, the BSS segment does not occupy actual space in the executable file; it only gets memory allocated and zeroed by the operating system when the program is loaded.
Example
; Demonstrates the use of the BSS segment
section .bss
buffer resb 256 ; Reserve a 256-byte buffer (uninitialized)
num_array resd 100 ; Reserve 100 double words (400 bytes)
section .data
; Initialized data
section .text
global _start
_start:
; Use the buffer in the BSS segment
mov byte [buffer], 'A' ; Write character 'A' to the buffer
; ...
mov eax, 1
mov ebx, 0
int 0x80
Putting uninitialized data in the BSS segment instead of the .data segment can reduce the executable file size. For example, a 10KB uninitialized buffer takes up no file size in the BSS segment, but if placed in the .data segment, it would increase the file by 10KB.
Segment Registers
The x86 architecture has 6 segment registers, used to track the currently used segments:
| Segment register | English full name | Purpose |
|---|---|---|
| CS | Code Segment | Points to the code segment, storing the segment base address where the currently executing instructions reside |
| DS | Data Segment | Points to the data segment, storing the segment base address for most data accesses |
| SS | Stack Segment | Points to the stack segment, storing the segment base address where the stack resides |
| ES | Extra Segment | Extra segment register, used for additional data segments such as string operations |
| FS | General Purpose | General-purpose segment register, often used for thread-local storage |
| GS | General Purpose | General-purpose segment register, often used for thread-local storage |
In 32-bit protected mode, programmers usually do not need to set segment registers manually; the operating system and linker handle it.
Memory Segmentation Diagram
The memory layout of a running program is as follows:
The approximate memory layout of a running program is as follows:
高地址 +-------------------+ | 栈 (Stack) | <-- SS:ESP 指向栈顶 | 向下增长 | +-------------------+ | | | 空闲内存 | | | +-------------------+ | BSS 段 (.bss) | 未初始化的全局变量 +-------------------+ | 数据段 (.data) | 已初始化的全局变量 +-------------------+ | 代码段 (.text) | 程序指令(只读) +-------------------+ | 保留区域 | 操作系统使用 +-------------------+ 低地址
Real Mode vs Protected Mode
| Feature | Real mode (16-bit) | Protected mode (32-bit) |
|---|---|---|
| Memory addressing | Segment address × 16 + offset | Segment selector looks up descriptor table + offset |
| Maximum memory | 1MB | 4GB (32-bit) |
| Memory protection | No protection | Has page-level and segment-level protection |
| Multitasking | Not supported | Supported |
| Addressing mode | segment:offset | selector:offset (via descriptor table) |
Other extensionsThis tutorial mainly introduces assembly programming in 32-bit protected mode. In this mode, the concept of segments is more of a logical division of memory regions, with physical addresses managed by the paging mechanism. You can simply understand the sections .data/.bss/.text as markers for different parts of the program in memory.