文本段包含程序的实际代码,即编译器发出的机器代码。最后一条语句的想法是,你的 C 程序和文本编辑器是完全一样的。它只是从内存中执行的机器代码指令。
例如,我们将采用以下代码,以及我刚刚想到的假设架构,因为我不记得 x86 汇编了。
while(i != 10)
{
x -= 5;
i++;
}
这将转化为以下说明
LOOP_START:
CMP eax, 10 # EAX contains i. Is it 10?
JZ LOOP_END # If it's 10, exit the loop
SUB ebx, 5 # Otherwise, subtract 5 from EBX (x)
ADD eax, 1 # And add 1 to i
JMP LOOP_START # And then go to the top of the loop.
LOOP_END:
# Do something else
这些是您的处理器可以理解的低级操作。然后这些将被翻译成二进制机器代码,然后存储在内存中。例如,考虑到我刚刚想到的操作和操作码之间的映射,实际存储的数据可能是 5、2、7、6、4、9。有关这实际上是如何发生的更多信息,请查看汇编程序和机器代码之间的关系。
-- Ninja-edit - 如果您接受上面 RBK 的评论,您可以使用 objdump 或类似的反汇编程序查看构成您的应用程序的实际说明。Visual Studio 中有一个,或者您可以在 Windows 上使用 OllyDbg 或 IDA。
因为程序的实际指令应该是只读的,所以不需要为程序的多次运行复制文本段,因为它应该始终相同。
至于您对数据段的问题,char* string
实际上将存储在该.bss
段中,因为它没有初始化程序。这是在程序运行之前(通过 crt0 或等效项)清除的内存区域,除非您给 GCC 一个我不记得的标志。该.bss
段是可读写的。
是的,堆栈段包含您的局部变量。实际上,它存储所谓的“堆栈帧”。其中一个是为您调用的每个函数创建的,它们相互堆叠。正如您所说,它包含诸如局部变量之类的内容,以及其他有用的位(例如调用函数的地址)以及其他有用的数据,以便在函数退出时可以恢复以前的状态。对于堆栈框架中实际包含的内容,您需要深入研究架构的 ABI(应用程序二进制接口)。