为什么我们需要针对不同的平台(例如Windows/Linux)进行编译?

Max*_*bit 4 c cpu assembly compilation cpu-architecture

我已经学习了关于CPU/ASM/C的基础知识,并且不明白为什么我们需要为不同的OS目标不同地编译C代码.编译器所做的是创建汇编程序代码,然后汇编到二进制机器代码.ASM代码当然因CPU架构(例如ARM)而不同,因为指令集架构不同.

但是当Linux和Windows在同一个CPU上运行时,MOVE/ADD/......之类的机器操作应该是相同的.虽然我知道有一些特定于操作系统的功能,比如打印到终端,但是这个功能可以由stdio.h的不同实现提供.而且,我可以创建一个非常基本的程序,只计算a + b而不打印任何东西,这样我就不需要任何特定于操作系统的代码.为什么我仍然需要为Linux和Windows编译而不是仅仅为我的Linux可执行文件添加.exe-Extension?

Sta*_*irl 7

即使CPU是相同的,仍然存在许多差异:

  • 不同的可执行格式
  • 可以使用不同的调用约定.例如,Windows要求被调用者保存xmm4-xmm5寄存器,而其他操作系统不需要这样.
  • 关于堆栈结构的不同约定.类Unix系统有一个" 红区 " 的概念,以帮助编译器生成更短的代码.执行环境必须遵守这样的概念以避免堆栈损坏.
  • 程序与具有不同ABI的不同标准库链接 - 字段顺序可能不同,可能存在其他扩展字段.
  • 标准库可以提供不同的功能集.在Linux上,libc提供了snprintf直接的功能,但在Windows上snprintf可能会static inline在头文件中实现为函数,该头文件实际上从C运行时调用另一个函数.这对程序员来说是透明的,但会为可执行文件生成不同的导入列表.
  • 在C和C++中,某些数据类型具有与操作系统相关的大小.例如,x86_64 long在Linux 上是8字节,在Windows 上是4字节.
  • 程序以不同的方式与操作系统交互:Linux程序可能直接进行系统调用,因为它们是文档和提供的接口的一部分,而在Windows上它们没有记录,程序应该使用提供的函数.
  • 与操作系统无关,但由不同编译器编译的程序可能无法互操作:可能会使用不同的标准库,例如C++名称修改可能会有所不同,使得无法将库相互链接,C++异常实现可能是不可互操作的.
  • 不同的文件系统结构.不仅Windows上的"\"和Unix上的"/"之间存在差异,而且"特殊文件"可能存在,也可能不存在,如"/ dev/null".

理论上可以解决此处列出的所有内容:可以编写自定义加载器以支持不同的可执行格式,如果整个程序使用相同的一组内容,则不同的约定和接口不会导致问题.这就是Wine之类的项目可以在Linux上运行Windows二进制文件的原因.问题是Wine必须在其他操作系统提供的功能之上模拟Windows NT内核的功能,从而降低实现效率.由于使用了不同的非互操作接口,因此这种程序在与本机程序交互时也存在问题.