汇编程序为什么要有单独的段?

8

为什么汇编程序要将数据段(.data/.bss)和代码段(.text)加载到不同的内存块中,而不是载入一个单独的内存块?

我的猜测是操作系统可以随意移动这些段或者对存储的数据类型进行内存优化。您有何想法?


节(section)而非段(segment)。这是可执行文件格式的一个特性。在16位代码中是段(segment),不确定您的情况是否如此。 - Hans Passant
"Section"和"Segment"是同义词(请参阅nasm文档)。 - CodyBugstein
3个回答

14

这不仅适用于汇编程序,也适用于操作系统的可执行文件格式,大多数操作系统决定将程序的各个部分分离成不同的节("segments")。

将可执行文件分成不同的节有几个好处,例如您提到的:

.bss:存储需要在程序启动时清零的内存信息。需要清零的内存是常见的,操作系统通常具有为分配清零内存而设计的特殊服务。如果您分配了一个1MB的全局数组,则无需在可执行文件中嵌入1MB的0- 您只需将该信息编码在.bss节中,操作系统将在程序启动时分配1MB。

.data:这是所有在程序启动时初始化为非零的数据。

.text:这是实际代码

还可以有许多其他节,例如包含引导代码的特殊节,需要运行以初始化程序但一旦运行就可以丢弃的节,或包含调试信息的节(除非您在调试器中运行程序,否则不需要将其加载到内存中)。另一个常见的节是只读数据节:

.rodata:包含不可写数据,例如程序中的所有字符串或常量数据。

此外,CPU可以对内存应用保护,例如可读/可写/可执行内存。将不同的节分开允许轻松地应用这些内存保护。例如,代码需要是可执行的,但是将数据设置为可执行可能不是一个好主意。只读节也可以更容易地在其他进程之间共享,代码和只读内存节可以在程序的多个实例之间共享。如果文本节的某些部分需要交换出来,它们可以直接丢弃,因为它们已经驻留在可执行文件本身中,而数据/bss节不能,则必须将它们交换到特殊的交换区域。


@nos 你所说的“在程序启动时需要被清零的内存”是什么意思? - CodyBugstein

3
通常你可以逐段地设置属性。例如,只读段让你可以一次性指定“只读”,然后在该段中放入只读数据,而不是对每个变量逐个指定只读。

0
不,我认为你误解了,分段概念不仅在汇编语言中使用,每一种机器特定的高级语言(如C、C++、Basic、Pascal等)都会在内部使用分段。
因为每一个C和C++程序都是通过GNU编译器(在Ubuntu的情况下)编译成汇编语言,编译器将适当的数据放入适当的段中,GAS汇编器将把这个汇编转换为目标代码字节。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接