编译器如何在内存中布置代码

mut*_*ity 8 memory compiler-construction assembly operating-system virtual-memory

好的,我有一点菜鸟学生的问题.

所以我很熟悉堆栈包含子程序调用,堆包含可变长度数据结构,全局静态变量分配给永久存储器位置.

但这一切如何在较低的理论水平上发挥作用?

编译器是否只是假设它从地址0到地址无穷大有一个完整的内存区域?然后开始分配东西?

它在哪里布局指令,堆栈和堆?在内存区域的顶部,内存区域的结尾?

那么它如何与虚拟内存一起使用?虚拟内存对程序是透明的吗?

很抱歉bajilion的问题,但我正在采用编程语言结构,它一直在指这些区域,我想在更实际的层面上理解它们.

非常感谢!

Dav*_*ger 7

全面的解释可能超出了本论坛的范围.整篇文章都致力于这一主题.但是,在简单的层面上,你可以这样看待它.

编译器不会在内存中布置代码.它确实假设它拥有整个内存区域.编译器生成目标文件,其中目标文件中的符号通常从偏移量0开始.

链接器负责将目标文件拉到一起,将符号链接到链接对象中的新偏移位置并生成可执行文件格式.

链接器也不在内存中布置代码.它将代码和数据打包成通常标记.text为可执行代码指令的部分以及.data全局变量和字符串常量之类的部分.(并且还有其他部分用于不同的目的)链接器可以提供操作系统加载器的提示,其中重定位符号,但加载器不必强制.

操作系统加载程序解析可执行文件并决定代码和数据在内存中的布局位置.其位置完全取决于操作系统.通常,堆栈位于比程序指令和数据更高的存储区域中并且向下增长.

每个程序都是编译/链接的,假设它有自己的整个地址空间.这就是虚拟内存的用武之地.它对程序完全透明,完全由操作系统管理.

虚拟内存的范围通常从地址0到平台支持的最大地址(不是无限).该虚拟地址空间由操作系统划分为内核可寻址空间和用户可寻址空间.假设在一个假设的32位操作系统上,上面的地址0x80000000是为操作系统保留的,下面的地址供程序使用.如果程序试图访问此分区上方的内存,它将被中止.

操作系统可以决定堆栈从最高可寻址用户存储器开始,并且随着位于更低地址的程序代码而增长.

堆的位置通常由您构建程序的运行时库管理.它可以在程序代码和数据之后的下一个可用地址开始.