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 NameEnglish NamePurposeCorresponding Section
Code SegmentCode SegmentStores executable machine instructionssection .text
Data SegmentData SegmentStores initialized global variablessection .data
Stack SegmentStack SegmentStores function call information and local variablesAutomatically 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

; File path: code_segment.asm
; 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

; File path: data_segment.asm
; 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

; File path: bss_segment.asm
; 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 registerEnglish full namePurpose
CSCode SegmentPoints to the code segment, storing the segment base address where the currently executing instructions reside
DSData SegmentPoints to the data segment, storing the segment base address for most data accesses
SSStack SegmentPoints to the stack segment, storing the segment base address where the stack resides
ESExtra SegmentExtra segment register, used for additional data segments such as string operations
FSGeneral PurposeGeneral-purpose segment register, often used for thread-local storage
GSGeneral PurposeGeneral-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

FeatureReal mode (16-bit)Protected mode (32-bit)
Memory addressingSegment address × 16 + offsetSegment selector looks up descriptor table + offset
Maximum memory1MB4GB (32-bit)
Memory protectionNo protectionHas page-level and segment-level protection
MultitaskingNot supportedSupported
Addressing modesegment:offsetselector:offset (via descriptor table)

This 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.

Other extensions