这种对应关系由汇编器(如 as)和链接器(如 ld 决定,并最终体现在可执行文件(如 ELF)的布局中,操作系统据此把它们加载到具体的内存地址。


一、二者关系概览

汇编语法中的 .section 可执行文件中的段(ELF) 内存中的区域(虚拟地址空间)
.text .text 代码段(Code Segment)
.data .data 数据段(Data Segment)
.rodata .rodata 只读数据区(Read-Only Data)
.bss .bss BSS 段(零初始化数据)
堆(Heap)
栈(Stack)

二、段如何变成内存映射

以 Linux 上典型 ELF 格式为例:

  1. 你写的 .section -> 被汇编器变成 节(section)
  2. 链接器将节合并成段(segment),比如 .text 节被放入 PT_LOAD 类型的 text 段
  3. 程序执行时,内核的 ELF 加载器按段加载到内存相应位置(通常通过 mmap

三、程序运行时的内存段布局(虚拟地址空间)

一个 ELF 程序在 Linux 下的典型内存布局如下:

0x00400000 ────────────▶ 代码段 (.text, 只读可执行)
           ────────────▶ 只读数据段 (.rodata, 只读)
           ────────────▶ 数据段 (.data, 可读写)
           ────────────▶ BSS段 (.bss, 初始为0)
           ────────────▶ 堆区 heap(动态增长)
0x7fffc000 ────────────▶ 栈 stack(向下增长)

这些区域的属性由 .section + 链接脚本(如 linker.ld)共同决定。


四、例子对照:从汇编到内存

.section .text
_start:
    mov $msg, %rdi
    call print

.section .data
msg: .asciz "hello\n"

.section .bss
.lcomm buffer, 64
  • .text → 映射到虚拟地址如 0x400000,只读可执行
  • .data → 映射到如 0x600000,读写可改
  • .bss → 不在 ELF 文件中占空间,但运行时分配(自动清零)
  • .rodata(若有) → 映射到如 0x500000,只读不能写

五、如何验证这点?

你可以通过以下命令查看 ELF 段与内存布局的映射:

readelf -S your_program   # 查看 .section
readelf -l your_program   # 查看 segment 映射
objdump -h your_program   # 查看段的地址、权限

或者运行后,在 proc 中看真实内存映射:

cat /proc/$(pidof your_program)/maps

六、总结

  • 汇编的 .section 指令决定了数据/代码的类别
  • 链接器根据 .section 生成 ELF 文件的段
  • 操作系统将段映射到虚拟内存空间,形成代码段、数据段、BSS、堆和栈
  • 所以:.section 与程序运行时内存布局是一一对应的,极为紧密