我写了这个问题:在编译过程的每个步骤中,什么影响生成的机器码?然后意识到这太宽泛了。因此,我将尝试用不同的问题来询问它的每个组成部分。
我要问的第一个问题是,给定一个任意的c++文件,什么会影响它产生的可执行二进制文件?到目前为止,我理解以下每一个都发挥了作用
- CPU架构如x86_64, ARM64, Power PC, Microblaze等
- 机器的内核,如Linux内核v5.18, v5.17, Windows内核版本,Mac内核版本等
- 操作系统,如Debian、CentOS、Windows 7、Windows 10、Mac OS X Mountain Lion、Mac OS X Sierra。
- 不确定内核变化之外的操作系统变化
- 最后使用工具进行编译、汇编和链接。像GCC, Clang, Visual Studio (VS), GNU汇编器,GNU编译器,VS编译器,VS链接器等。
我有两个问题是
- 是否有一些其他组件,我遗漏了,影响如何最终的可执行文件看起来像?
- 操作系统对最终的可执行机器码有影响吗?因为我以为这都是内核的问题。
我认为您缺少的主要是应用程序二进制接口。ABI的一部分是调用约定,它决定了寄存器使用和参数传递的某些属性,因此这些直接影响生成的机器码。
内核有一个加载程序,该加载程序可以处理文件格式,如ELF或PE。它们通过决定过程的布局和程序代码的方式来影响机器码。数据如何加载到内存中,以及机器代码指令如何访问数据和其他代码。例如,有些环境需要与位置无关的代码,这会影响一些机器代码指令。
CPU架构如x86_64、ARM64、Power PC、Microblaze等
是的。指令集体系结构定义了可用的指令,进而定义了可用的CPU寄存器以及如何使用它们以及指针等东西的大小。
机器的内核,如Linux内核v5.18, v5.17, Windows内核版本,Mac内核版本等
没有。操作系统的选择会影响ABI,这是非常相关的。
Debian、CentOS、Windows 7、Windows 10、Mac OS X Mountain Lion、Mac OS X Sierra等操作系统
操作系统通常指定ABI,这很重要。
用于编译、汇编和链接的工具。像GCC, Clang, Visual Studio (VS), GNU汇编器,GNU编译器,VS编译器,VS链接器等。
当然,不同的工具产生一些不同的机器码,有时差异是等效的,尽管对于某些输入,有些工具产生比其他工具更好的机器码。