c++ - C 和汇编程序实际上编译成什么?

标签 c++ c compiler-construction linker assembly

所以我发现 C(++) 程序实际上并不能编译为普通的“二进制”(我可能在这里弄错了一些东西,在那种情况下我很抱歉 :D)而是一系列的东西(符号表,操作系统相关的东西,...)但是...

  • 汇编器是否“编译”为纯二进制?这意味着除了预定义字符串等资源之外没有额外的东西。

  • 如果 C 编译为普通二进制以外的其他内容,那么小型汇编程序引导加载程序如何将指令从 HDD 复制到内存并执行它们?我的意思是,如果操作系统内核(可能是用 C 编写的)编译为不同于普通二进制的东西 - 引导加载程序如何处理它?<​​/p>

编辑:我知道汇编器不会“编译”,因为它只有你机器的指令集——我没有找到一个关于汇编器“汇编”到什么的好词。如果你有的话,把它留在这里作为评论,我会改变它。

最佳答案

C 通常编译为汇编器,只是因为这让可怜的编译器编写者的生活变得轻松。

汇编代码总是汇编(而不是“编译”)成可重定位的目标代码。您可以将其视为二进制机器代码和二进制数据,但包含大量装饰和元数据。关键部分是:

  • 代码和数据出现在命名的“节”中。

  • 可重定位目标文件可能包含标签的定义,这些标签指的是部分中的位置。

  • 可重定位的目标文件可能包含“洞”,这些“洞”将被其他地方定义的标签值填充。这种洞的正式名称是relocation entry

例如,如果你编译和汇编(但不链接)这个程序

int main () { printf("Hello, world\n"); }

你很可能会得到一个可重定位的目标文件

  • 包含 main

  • 机器码的 text 部分
  • main 的标签定义,指向文本部分的开头

  • 一个 rodata(只读数据)部分,包含字符串文字 "Hello, world\n"

  • 依赖于 printf 的重定位条目,它指向文本部分中间的调用指令中的“漏洞”。

如果您在 Unix 系统上,可重定位目标文件通常称为 .o 文件,如 hello.o,您可以使用名为 nm,你可以从一个叫做 objdump 的更复杂的工具获得更详细的信息。

我教了一门涵盖这些主题的类(class),我让学生编写一个汇编器和链接器,这需要几周时间,但是当他们完成后,他们中的大多数人都可以很好地处理可重定位的目标代码。这不是一件容易的事。

关于c++ - C 和汇编程序实际上编译成什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2135788/

相关文章:

php - 有没有一个工具可以将php内置函数转换为c实现?

compiler-construction - 为什么 JIT 代码比编​​译或解释的代码消耗更多的内存?

java - 如何修复解析错误(使用 LOOKAHEAD)

c++ - 如何在 OpenGl 中动态添加顶点?

c - 在 C 中返回多维字符数组

c++ - 将位分配给动态位集以在 C++ 中运行

c - 从 C 语言文件中读取 64 字节 block

编译器代码生成比较

c++ - 检查 qtreewidgetitem 复选框是否被选中

c++ - 使用无锁算法阻塞并发队列