【问题标题】:Why does the machine code depend on the OS type? [closed]为什么机器代码取决于操作系统类型? [关闭]
【发布时间】:2017-04-30 10:54:56
【问题描述】:

假设,我有一个用 C 语言编写的程序,我有两台相同的计算机,一台运行 Windows,另一台运行 linux。由于计算机是相同的,它们的处理器具有相同的指令集,因此编译后的机器代码应该是相同的。那么为什么我需要编译我的程序两次呢?假设,我不调用任何与操作系统相关的函数,或者依赖于实际操作系统的函数。

【问题讨论】:

  • 可执行格式不同。
  • 你无法避免调用操作系统函数或调用操作系统函数的东西。如果您希望您的程序具有可见的效果,例如打印一个数字,则不是。
  • 为什么它们不同?它与保护模式/内核模式有关吗?如果处理器相同,它们不应该运行相同的机器代码吗?
  • 它们运行相同的机器代码,但操作系统的接口不同。
  • 即使您不调用“操作系统特定函数”,编译器也会这样做。至少在程序结束时“返回操作系统”会完成

标签: c assembly compilation linker machine-code


【解决方案1】:

机器码不依赖操作系统,同一个CPU都是一样的。

如果您在目标 CPU 模式下(比如 x86 32b)执行了与操作系统无关的一段机器代码,并将其加载到一些 ROM 内存中,以便它可用,您可以在 Windows 和 Windows 中映射该部分 ROM linux(通过完全不同的OS API来映射物理内存并赋予它可执行权限),然后跳转到那里..并且ROM中的机器代码将以相同的方式运行。

那么为什么我需要编译我的程序两次呢?假设,我不调用任何与操作系统相关的函数,或者依赖于实际操作系统的函数。

您不必这样做。但通常您希望代码中有一些入口点,通常提供通用入口点的最简单方法是遵循 OS 定义的 ABI(应用程序二进制接口),因此例如在 32b 窗口中,您从堆栈中读取参数,而在 64b 中linux 你在寄存器中接收参数(如果可能的话)。如果您不调整您的过程序言代码以以正确的方式选择参数,它将在“其他”操作系统中以错误的输入运行,而不是为其编写。

但是机器码本身,CPU指令,是一样的。

也就是说,在 x86 上,由于历史上的向后兼容性,情况有点棘手,因此 CPU 可以处于 16b 模式、32b [受保护] 模式(其中几个加上不同的设置)或 64b 模式。 80386 CPU指令mov eax,1对16b模式和32b模式有不同的机器码编码。

但只要你的目标是相同的 CPU 模式,相同指令的机器码就会以相同的方式编译。您只需编写不同的源代码以遵循不同的 ABI。

而且可执行文件...每种格式都不一样,甚至不是“每个操作系统”,同样由于历史原因,几乎所有 x86 操作系统都支持几种可执行文件格式,因此文件中存储的机器码周围的元数据(操作系统在将机器代码加载到内存并设置运行时使用)是完全不同的。

实际的例子是linux appwine,它可以执行windows可执行文件,通过提供假的操作系统挂钩点来模拟windows操作系统,并通过理解windows可执行二进制文件,从而正确地将它们加载到内存中。此类 Windows 应用程序的机器代码是本地运行的,无需任何进一步的修补。

【讨论】:

  • 还有一个注意事项。汇编程序通常会生成“目标文件”,这些文件又是特定于工具链的格式,因此 Microsoft Visual Studio 使用不同的“.obj”文件来存储相同的汇编机器代码,而不是 linux 上的 gcc 生成“.o”。目标文件的机器代码部分相同,但允许链接此类文件的元数据可能完全不同(加上调试元数据的不同格式等)。所以这是另一个原因,为什么您必须多次编译相同的源代码,但不是针对每个操作系统,而是针对每个工具链。
  • 另外,ABI 在类型大小上的差异:long 在 x86-64 Windows 上是 32 位,但在 System V x86-64 ABI 中是 64 位。因此,相同的 C 结构在为不同的 ABI 编译时可能意味着不同的东西,更不用说单个变量的大小不同(因此在机器代码中需要不同的操作数大小,以及本地变量的不同堆栈布局等)
  • 它比“每个工具链”更糟糕。它是每个版本的工具链。对于来自特定供应商的所有工具,不能永久保证中间文件的二进制兼容性。我不确定 GCC 人员是否尝试在此处提供向后兼容性,但 Microsoft 明确没有。 (实际上,这颇具讽刺意味。)跨工具链唯一起作用的是调试信息,因为它具有标准化的格式。但是,当然,关于标准的最好的事情是有很多可供选择:COFF、ELF、CodeView、PDB,... :-)
  • 因此,如果您在可执行文件中剥离元数据(特定于操作系统),如果使用相同的 CPU 架构,任何操作系统上的机器代码是否相同?即使程序包含一些系统调用?
  • @CharanSai 如果程序包含一些系统调用,那也是机器代码,并且该部分因操作系统而异。与操作系统无关的一切都可以相同,但是如果您将学习一点汇编,您会发现存在 [不同] 操作系统约定,甚至包括代码的不同部分如何在它们之间传递参数。因此,即使没有系统调用,生成的机器代码也可能略有不同,但对于 CPU 本身来说,它是相同的指令集。换个角度想,CPU 不知道操作系统在运行什么,操作系统也不会修改 CPU 指令,只是用不同的方式使用它们。
猜你喜欢
  • 1970-01-01
  • 2011-07-03
  • 2011-10-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-09-06
  • 1970-01-01
  • 2012-08-02
相关资源
最近更新 更多