为什么机器码依赖于 OS 类型?
Why does the machine code depend on the OS type?
假设,我有一个用 C 编写的程序,我有两台相同的计算机,一台是 运行 Windows,另一台是 linux。由于计算机是相同的,它们的处理器具有相同的指令集,因此编译后的机器码应该是相同的。那么为什么我需要编译我的程序两次呢?假设,我不调用任何 OS 相关的函数,或者一些依赖于实际 OS.
的函数
机器码不依赖OS,同一个CPU。
如果您在目标 CPU 模式下(假设 x86 32b)执行了 OS 一段不可知的机器代码,并将其加载到一些 ROM 内存中,因此它将可用,您可以在 Windows 和 linux 中映射那部分 ROM(通过完全不同的 OS API 来映射物理内存并赋予它可执行权限),然后跳转到那里......和ROM 中的机器代码将以相同的方式 运行。
So why do I need to compile my program twice? Suppose, I dont call any OS-related function, or something that depends on the actual OS.
您不必这样做。但通常你需要一些进入你的代码的入口点,通常如何提供通用入口点的最简单方法是遵循 OS 定义的 ABI(应用程序二进制接口),例如在 32b windows 你从堆栈读取参数,在 64b linux 中,您在寄存器中接收参数(如果可能)。如果你不调整你的程序序言代码以正确的方式选择参数,它将在 "other" OS 中使用错误的输入运行,而不是为它编写的。
但是机器代码本身,CPU 指令,是相同的。
也就是说,在 x86 上,由于历史向后兼容性,情况有点复杂,所以 CPU 可以处于 16b 模式、32b [保护] 模式(其中几个加上不同的设置) , 或 64b 模式。 80386 CPU 指令 mov eax,1
对于 16b 模式和 32b 模式具有不同的机器码编码。
但是只要你针对的是同一个CPU模式,同一条指令的机器码也是按照同样的方式编译的。您只需以不同的方式编写源代码以遵循不同的 ABI。
和可执行文件...每种格式都不同,甚至 "per OS",同样由于历史原因,几乎所有 x86 OS 都支持多种可执行文件格式,因此元数据存储在文件中的机器代码(由 OS 在将机器代码加载到内存中并为 运行 设置它时使用)完全不同。
实际例子是linux app wine
,它可以执行windows个可执行文件,通过提供假的OS钩子点来模拟windows [=47] =],并通过理解 windows 可执行二进制文件,从而正确地将它们加载到内存中。这种 windows 应用程序的机器代码是 运行 原生的,没有任何进一步的补丁。
假设,我有一个用 C 编写的程序,我有两台相同的计算机,一台是 运行 Windows,另一台是 linux。由于计算机是相同的,它们的处理器具有相同的指令集,因此编译后的机器码应该是相同的。那么为什么我需要编译我的程序两次呢?假设,我不调用任何 OS 相关的函数,或者一些依赖于实际 OS.
的函数机器码不依赖OS,同一个CPU。
如果您在目标 CPU 模式下(假设 x86 32b)执行了 OS 一段不可知的机器代码,并将其加载到一些 ROM 内存中,因此它将可用,您可以在 Windows 和 linux 中映射那部分 ROM(通过完全不同的 OS API 来映射物理内存并赋予它可执行权限),然后跳转到那里......和ROM 中的机器代码将以相同的方式 运行。
So why do I need to compile my program twice? Suppose, I dont call any OS-related function, or something that depends on the actual OS.
您不必这样做。但通常你需要一些进入你的代码的入口点,通常如何提供通用入口点的最简单方法是遵循 OS 定义的 ABI(应用程序二进制接口),例如在 32b windows 你从堆栈读取参数,在 64b linux 中,您在寄存器中接收参数(如果可能)。如果你不调整你的程序序言代码以正确的方式选择参数,它将在 "other" OS 中使用错误的输入运行,而不是为它编写的。
但是机器代码本身,CPU 指令,是相同的。
也就是说,在 x86 上,由于历史向后兼容性,情况有点复杂,所以 CPU 可以处于 16b 模式、32b [保护] 模式(其中几个加上不同的设置) , 或 64b 模式。 80386 CPU 指令 mov eax,1
对于 16b 模式和 32b 模式具有不同的机器码编码。
但是只要你针对的是同一个CPU模式,同一条指令的机器码也是按照同样的方式编译的。您只需以不同的方式编写源代码以遵循不同的 ABI。
和可执行文件...每种格式都不同,甚至 "per OS",同样由于历史原因,几乎所有 x86 OS 都支持多种可执行文件格式,因此元数据存储在文件中的机器代码(由 OS 在将机器代码加载到内存中并为 运行 设置它时使用)完全不同。
实际例子是linux app wine
,它可以执行windows个可执行文件,通过提供假的OS钩子点来模拟windows [=47] =],并通过理解 windows 可执行二进制文件,从而正确地将它们加载到内存中。这种 windows 应用程序的机器代码是 运行 原生的,没有任何进一步的补丁。