![]() |
1
8
不同的操作系统支持不同的二进制格式(例如elf与coff)、不同的动态链接器(在分发二进制文件之后,运行时链接了*.so、*.dll和*.dylib文件),并为使用操作系统提供的功能提供不同的函数集和库集。 例如,可以通过单个Unix规范/IEEE Std.1003.1(POSIX)来处理不同的功能集,该规范规定在所有操作系统中为各种操作系统任务提供一组功能(不幸的是,并非所有OSS——ahem, 窗户 --遵守)。对于二进制格式(以及CPU指令集体系结构),处理这一问题的一种方法是分发一些更高级别的二进制格式(字节码),然后对目标指令集和二进制格式进行实时转换(尽管这更多的是在去做吧…这仍然需要完成)。例如,低级虚拟机(llvm)提供了这种转换。 |
![]() |
2
8
不同的操作系统提供不同的
system calls
以及调用这些系统调用的不同机制。例如,当posix提供
此外,在组装级别上也存在差异。您使用什么程序集代码来调用函数?不同的操作系统期望不同 calling conventions . 操作系统也不一定同意可执行二进制文件的格式,也不一定同意动态链接等其他机制。 另一个需要考虑的问题是并发性以及操作系统如何处理它。有些操作系统在内核级别识别线程,而另一些则不识别。有些人可能只喜欢使用多个进程,有些人可能会使用完全不同的模型。API是不同的,抽象可能是不同的。例如,一个操作系统可能使用锁和信号灯,另一个操作系统可能使用消息传递。 |
![]() |
3
6
因为,首先,平台之间的操作系统接口能力是不一致的。即使在Linux/x86、Windows和Mac/Intel(它们可能都使用相同的CPU)之间,做事情的方式也可能大不相同。 因此,虽然编译器可能会生成可以工作的对象文件,但一旦将这些对象链接到特定于平台的库,它们就变得不可移植。
一个例子是内存分配。当您想从Unix下的操作系统请求更多内存时,可以使用
另一方面,窗户可以提供
|
![]() |
4
1
您是对的,编译器只关心为特定的目标CPU生成正确的汇编程序指令。但编译器并不是独立的——应用程序通常必须与主机操作系统接口才能正常运行。 因此,问题不在于编译器本身,而在于每个操作系统提供的一组标准库,用于执行诸如访问文件、分配内存或与图形窗口系统交互等常见操作。例如,虽然Windows XP和Solaris x86的代码将编译为同一组机器代码指令,但代码必须对与操作系统的接口进行不同的调用。 专有编译器仅与为其设计的操作系统的头文件和库捆绑在一起。另外,更不可知论的编译器(如GNUGCC)在跨不同操作系统编译到相同CPU类型时会共享大量代码。 |
![]() |
5
0
是的,机器代码由CPU直接运行。但是,即使是32位的“x86”指令集,也就是机器代码,多年来一直在进行修订。但一般来说,为体系结构编译的代码应该在其他系统上运行。更大的问题是编译它的编译器和操作系统 |
![]() |
6
0
是的,的确如此。例如,这就是如何在Wine下运行Linux中的Windows应用程序。您可以出于一个以上的原因直接运行程序。例如,可执行文件的格式在不同的系统中是不同的,因此系统通常对如何加载和执行其他可执行文件一无所知。除此之外,大多数程序都想调用系统例程和一些库函数,这里我们讨论的是关于如何在每个系统中执行的完全不同的协议集。 |
|
7
0
你的问题是,“所以相同的机器代码应该在每个操作系统上运行,只要它是相同的体系结构,不是吗?”不正确。 机器代码运行在硬件上,而不是操作系统上。 操作系统向用户/系统程序提供服务,这些服务在每个操作系统中的实现方式不同。为了便于论证,如果您将程序的机器代码从架构“A”上的操作系统“X”中取出,并将其直接送入具有相同架构“A”的操作系统“Y”,CPU将能够执行指令,但这可能(并且几乎总是)导致程序崩溃(因为与其他人已经提到的不同的实施问题)。 |
![]() |
George S. · 是否存在基于元组的控制流语句内部表示? 7 年前 |
![]() |
FlatAssembler · 在x86程序集中计算exp(x) 7 年前 |
![]() |
cib · 即时编译和动态编译有什么区别? 7 年前 |
![]() |
Artemis · 寄存器与指令之间的差异 7 年前 |
![]() |
Sam · 了解go工具编译和链接命令 7 年前 |