源代码程序的代码段和数据段在流程执行过程中是如何真正处理和分离的?

问题描述 投票:0回答:1

考虑下图显示的 RAM,其中存储了一个非常简单的程序,分为指令块和数据块。该示例与 Charles Petzold 所著的《Code》一书中的示例非常相似:

Click to see the full resolution image

如您所见,有一个指令块和一个数据块。在书中,这个 RAM 被放置在一台基本的计算机中,您必须使用一些开关(就像旧的 Altair 8800 一样)手动输入数据和指令。为了让机器开始执行指令,你必须设置指令块的起始地址,然后机器开始依次执行一条指令。基本上这个程序所做的就是将值1加载到累加器中,然后添加5,将结果存储在地址000Ch(h代表十六进制)中,最后用Halt指令停止执行。

现在,当我尝试将从本书中获得的知识与 C 源代码的编译方式联系起来时,我有点困惑。具体来说,是代码段和数据段之间存在某种分离的阶段。考虑这个简单的源代码:

#include <stdlib.h>
#include <stdio.h>

int test=10;

int main(){

    test ++;
    return 0;
}

现在,我的想法是编译器应该告诉计算机执行这样的机器指令:

int test=10; // -> STORE [addressX],10 

int main(){

    test++; // -> LOAD A,[addressX]
            // -> INR  A
            // -> STORE [addressX],A

    return 0;
}

根据维基百科的定义,数据段“包含已初始化的静态变量,即具有已定义值且可以修改的全局变量和局部静态变量”。

在我的简单示例中,变量 test 是一个全局变量。

但是,我的想法是,在将变量放入 RAM 的数据段之前,必须调用某种机器指令(例如 STORE)。不然全局变量怎么存到RAM里面呢?

到底发生了什么,我在这里展示的简单源代码是如何真正分为文本段和数据段的?这个例子的文本段到底是什么?那么数据部分呢?

c compiler-construction ram
1个回答
1
投票

我可以解释 Windows 上的大致工作原理。

首先,书中给出的信息不适用于当今的操作系统。大多数操作系统(如Windows、Linux等)都有一个可执行文件格式,它描述了代码和数据如何存储在文件中、如何映射到RAM、从哪里开始执行代码等。在 Windows 上,该格式称为

Portable Executable
。 PE格式由零个或多个
sections
组成,用于存储代码和其他数据。区段包含一些重要的信息,例如操作系统如何在文件中找到该区段的数据、如何将这些数据映射到内存、内存中的这些数据将采用什么样的保护方法等。部分还可以有一个名称,例如
.text
.data
.bss
.idata
.rdata
,提供有关该部分包含何种数据的线索。

当您在 Windows 上使用 MSVC 编译和链接代码时,您的程序就有了一个可移植的可执行文件。该 PE 文件将包含一个或多个部分。对于您的示例,它可能有一个用于代码的

.text
,一个用于初始化数据的
.data
,以及一个用于从其他模块导入的
.idata
部分。
.text
部分包含已编译的机器代码,
.data
部分包含变量
test
的值10的数据。当您执行该文件时,操作系统加载程序将尝试加载、解析并将其映射到为其进程创建的内存中。

因此,您不需要 STORE 指令来在 RAM 中存储和初始化数据。程序中的所有数据都位于相应的部分,并将由加载器映射到内存中。

© www.soinside.com 2019 - 2024. All rights reserved.