繁体   English   中英

C编译程序使用哪些段?

[英]What segments does C compiled program use?

我在OSDev wiki上看到,x86架构的保护模式允许您为代码和数据创建单独的段,而您无法写入代码段。 Windows(是的,这是平台)将新代码加载到代码段中,并在数据段上创建数据。 但是,如果是这种情况,程序如何知道它必须将段切换到数据段? 如果我理解正确,所有地址指令都指向您运行代码的段,除非您切换描述符。 但我也读到,如此流行的平面内存模型允许您在一个段内运行代码和数据。 但我只在与汇编程序有关的情况下阅读此内容。 那么,请问,Windows上的C编译代码是什么情况? 谢谢。

您阅读的信息已过时。 自1993年以来的Windows版本使用平坦的32位虚拟内存空间。 CS和DS段寄存器的值不再重要,无法更改。 现在仍然存在代码与数据的概念,现在由内存页属性实现。 查看在VirtualProtectEx()API函数的flNewProtect参数中传递的允许值。

您很少自己使用此API,属性由可执行映像加载程序和堆管理器设置。

解释中的有两个含义:

  • 8086内存地址段
  • 对象模块程序部分段

第一个与加载到80386+段寄存器中的内容有关; 它包含一个物理内存起始地址,内存分配长度,允许的读/写/执行访问,以及它是从低到高增长,反之亦然(加上一些更模糊的标志,如“复制引用”)。

第二个含义是目标模块语言的一部分。 基本上,有一个名为code的段,一个名为data的段(包含初始化的数据),以及一个名为bss未初始化数据的段(以20世纪60年代汇编程序的伪指令命名,表示Block Starting with Symbol )。 当链接器组合对象模块时,它将所有代码段排列在一起,将所有数据段排列在其他地方,并将bss放在一起。 当加载程序映射内存地址时,它会查看总代码空间并分配至少该大小的CPU内存分配,并将该段映射到代码(在虚拟内存情况下)或将代码读入已分配的内存中 - 它必须暂时将内存设置为可写数据。 写保护通过CPU的分页机制以及段寄存器完成。 这是为了保护代码写入尝试,例如,通过错误的数据地址。 加载程序也为两个数据段组执行类似的设置。 (除此之外,还有设置堆栈段并分配它,并映射共享映像。)

就x86执行指令而言,每个操作数都有一个相关的段寄存器。 有时这些是明确的,有时它们是隐含的。 通过CS隐式访问代码,通过SS进行堆栈,无论何时涉及ESPEBP寄存器,都隐含代码,并且对大多数其他操作数隐含DS ESFSGS必须在所有其他情况下指定为覆盖,但某些字符串指令(如movscmps 在平面模型中,尽管CS不允许写入,但所有段寄存器都映射到相同的地址空间。

因此,为了回答您的上一个问题,CPU一次设置了四个(或更多)段寄存器,以访问进程的扁平虚拟内存空间。 检查每个操作数访问是否适合于该指令(如不增加CS地址),并且还由寻呼保护单元检查是否允许。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM