memory - 编译器如何在内存中布局代码

标签 memory assembly compiler-construction operating-system virtual-memory

好的,我有一个菜鸟学生的问题。

所以我熟悉堆栈包含子例程调用,堆包含可变长度数据结构,全局静态变量分配给永久内存位置的事实。

但是,这一切在理论层面上是如何运作的呢?

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

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

然后这如何与虚拟内存一起工作?虚拟内存对程序是透明的?

很抱歉有一个问题,但我正在学习编程语言结构,它一直在引用这些区域,我想在更实际的层面上理解它们。

非常感谢!

最佳答案

全面的解释可能超出了本论坛的范围。整篇文章都致力于这个主题。但是,从简单的角度来看,您可以这样看待它。

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

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

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

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

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

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

操作系统可能会决定堆栈从最高可寻址用户内存开始,并随着位于低得多的地址的程序代码而向下增长。

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

关于memory - 编译器如何在内存中布局代码,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19101449/

相关文章:

assembly 多重定义

assembly - MASM 字符串指令 - 在实模式下段寄存器覆盖前面的 LEA?

c++ - 控制台应用程序不会立即关闭

c - 处理器的最低要求是什么才能为其编写 C 编译器?

gcc - 构建 R 包时如何链接静态库

c - 为什么 malloc 返回 NULL 有足够的内存并且总是在同一点?

iOS黑屏大问题

PHP - 全局变量的性能和内存问题

memory - Redis 哈希结构并没有像描述的那样提高内存效率

C 预处理器和 "_asm _emit"指令