程序如何知道bss段的位置

据我了解,x86具有专用寄存器,用于指向代码段,数据段和堆栈段的指针,但不包括bss段和堆段。 电脑如何记住这些细分市场在哪里? 特别是堆,因为bss直接在数据之后,但堆经常放在内存中的不同位置。


堆通常由与您的代码(静态或动态)链接的C runtine创建。 它决定虚拟地址中的地址,调用操作系统提供的系统调用来映射页面,并将地址存储在由malloc(和函数族)使用的一些数据结构中。 所有这些代码要么在调用main之前执行,要么在二进制文件中静态初始化。

至于bss部分,如你所知它充满了所有的零。 该二进制文件具有.bss段大小和基地址的信息。 加载器将页面映射到该虚拟地址,并用零清除它们(以有效的方式)。

如果在Windows上运行dumpbin /HEADERS binary.exe您可以看到bss段的地址及其大小。 在Linux上你可以使用objdump 。 我相信所需的标志是-x

关于你的问题,如果偏移量在指令中被硬编码,他们如何能够被移动 -

该二进制文件还有一个称为重定位表的表,该表具有访问特定段上的这些值的所有指令的地址。 加载器可能会决定将该段放置在其他位置(通常在Linux中加载多个dll或共享库时发生)。 在这种情况下,它会修补看重定位表的所有指令。 它实际上改变了指令中的偏移量。 这是由加载程序在执行main之前完成的。

当然,这有一个开销,只有在重定位信息可用时才能完成。 某些二进制文件可能会选择省略重定位表,并且在这种情况下,如果该部分不能放置在指定位置,则该二进制文件无法加载。

希望能够消除一些混淆。


实际上,简单的答案是,“bss段”只是可执行文件中的一个数字,它告诉加载程序为零初始化全局数据预留了多少数据。 而已。

在保留并将该内存设置为零之后,程序的运行时启动(从Fortran,C或针对特定平台的任何编译)现在保留更多的内存,并在那里设置堆,然后决定在哪里该堆栈要走了。 在更多平台特定的初始化之后,控制最终被转移到可执行文件中指示的程序入口点,并且控制被转移到那里。 现在只有这个节目是“现场”的。


据我了解,x86具有专用寄存器,用于指向代码段,数据段和堆栈段的指针,但不包括bss段和堆段。 电脑如何记住这些细分市场在哪里? 特别是堆,因为bss直接在数据之后,但堆经常放在内存中的不同位置。

你正在为重叠的术语而苦恼。 段可以指分段内存模型下的内存段(如在64位以前的X86中使用的那样)。 段也可以指由链接器创建的具有公共访问属性的内存块。

你的问题似乎是指第二种用法。

你也似乎遭受了过于简单化的记忆观点。 首先,没有堆段。 堆是一个或多个读/写数据块。

其次,链接器可以创建多个需求零(bss)段。 链接器也可以按任意顺序在内存中放置段

第三,只有在加载时才需要分段知识。 段被加载后,它们只是内存。

链接地址: http://www.djcxy.com/p/82381.html

上一篇: How does a program know where the bss segment is located

下一篇: memory segments and physical RAM