简体   繁体   English

C编译程序使用哪些段?

[英]What segments does C compiled program use?

I read on OSDev wiki, that protected mode of x86 architecture allow you to create separate segments for code and data, while you cannot write into code section. 我在OSDev wiki上看到,x86架构的保护模式允许您为代码和数据创建单独的段,而您无法写入代码段。 That Windows (yes, this is the platform) loads new code into code segment, and data are created on data segment. Windows(是的,这是平台)将新代码加载到代码段中,并在数据段上创建数据。 But, if this is the case, how does program know it must switch segments to the data segment? 但是,如果是这种情况,程序如何知道它必须将段切换到数据段? Becouse if I understand it right, all adress instructions point to the segment you run the code from, unless you switch the descriptor. 如果我理解正确,所有地址指令都指向您运行代码的段,除非您切换描述符。 But I also read, that so colled flat memory model allows you to run code and data within one segment. 但我也读到,如此流行的平面内存模型允许您在一个段内运行代码和数据。 But I read this only in connection to assembler. 但我只在与汇编程序有关的情况下阅读此内容。 So, please, what is the case with C compiled code on Windows? 那么,请问,Windows上的C编译代码是什么情况? Thanks. 谢谢。

The info you read is outdated. 您阅读的信息已过时。 Windows versions since ~1993 use a flat 32-bit virtual memory space. 自1993年以来的Windows版本使用平坦的32位虚拟内存空间。 The values of the CS and DS segment registers no longer matter and cannot be changed. CS和DS段寄存器的值不再重要,无法更改。 There is still a notion of code vs data, now implemented by memory page attributes. 现在仍然存在代码与数据的概念,现在由内存页属性实现。 Review the allowed values passed in the flNewProtect argument for the VirtualProtectEx() API function . 查看在VirtualProtectEx()API函数的flNewProtect参数中传递的允许值。

You very rarely use this API yourself, the attributes are set by the executable image loader and the heap manager. 您很少自己使用此API,属性由可执行映像加载程序和堆管理器设置。

There are two meanings for segment in the explanation: 解释中的有两个含义:

  • an 8086 memory address segment 8086内存地址段
  • an object module program section segment 对象模块程序部分段

The first is related to what is loaded into an 80386+ segment register; 第一个与加载到80386+段寄存器中的内容有关; it contains a physical memory start address, memory allocation length, permitted read/write/execute access, and whether it grows from low to high or vice versa (plus some more obscure flags, like "copy on reference"). 它包含一个物理内存起始地址,内存分配长度,允许的读/写/执行访问,以及它是从低到高增长,反之亦然(加上一些更模糊的标志,如“复制引用”)。

The second meaning is part of the object module language. 第二个含义是目标模块语言的一部分。 Basically, there is a segment named code , a segment named data (which contains initialized data), and segment for uninitialized data named bss (named for the pseudo instructions of 1960s assemblers meaning Block Starting with Symbol ). 基本上,有一个名为code的段,一个名为data的段(包含初始化的数据),以及一个名为bss未初始化数据的段(以20世纪60年代汇编程序的伪指令命名,表示Block Starting with Symbol )。 When the linker combines object modules, it arranges all the code segments together, all the data segments together elsewhere, and the bss together as well. 当链接器组合对象模块时,它将所有代码段排列在一起,将所有数据段排列在其他地方,并将bss放在一起。 When the loader maps memory addresses it looks at the total code space and allocates a CPU memory allocation of at least that size, and maps the segment to the code (in a virtual memory situation) or reads the code into the allocated memory—for which it has to temporarily set the memory as data writable. 当加载程序映射内存地址时,它会查看总代码空间并分配至少该大小的CPU内存分配,并将该段映射到代码(在虚拟内存情况下)或将代码读入已分配的内存中 - 它必须暂时将内存设置为可写数据。 The write-protection is done through the CPU's paging mechanism, as well as the segment register. 写保护通过CPU的分页机制以及段寄存器完成。 This is to protect code writing attempts through, for example, an errant data address. 这是为了保护代码写入尝试,例如,通过错误的数据地址。 The loader also does the similar setup for the two data segment groups. 加载程序也为两个数据段组执行类似的设置。 (Besides those, there is setting up a stack segment and allocating it, and mapping shared images.) (除此之外,还有设置堆栈段并分配它,并映射共享映像。)

As far as the x86 executing instructions, each operand has an associated segment register. 就x86执行指令而言,每个操作数都有一个相关的段寄存器。 Sometimes these are explicit, and sometimes they are implicit. 有时这些是明确的,有时它们是隐含的。 Code is implicitly accessed through CS , stack through SS which is implied whenever the ESP or EBP register is involved, and DS is implied for most other operands. 通过CS隐式访问代码,通过SS进行堆栈,无论何时涉及ESPEBP寄存器,都隐含代码,并且对大多数其他操作数隐含DS ES , FS , and GS must be specified as an override in all other cases, except for some of the string instructions like movs and cmps . ESFSGS必须在所有其他情况下指定为覆盖,但某些字符串指令(如movscmps In flat model, all the segment registers map to the same address space, though CS doesn't allow writing. 在平面模型中,尽管CS不允许写入,但所有段寄存器都映射到相同的地址空间。

So, to answer your last question, the CPU has four (or more) segment registers set up at once to access the flat virtual memory space of the process. 因此,为了回答您的上一个问题,CPU一次设置了四个(或更多)段寄存器,以访问进程的扁平虚拟内存空间。 Each operand access is checked for being appropriate to the instruction (like not incrementing a CS address) and also is checked by the paging protection unit for being allowed. 检查每个操作数访问是否适合于该指令(如不增加CS地址),并且还由寻呼保护单元检查是否允许。

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

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