编译的程序实际上是真正的二进制吗

时间:2011-07-27 01:16:56

标签: compiler-construction operating-system machine-language

例如,当我编译一个C应用程序时,输出的文件读取为二进制文件还是操作系统然后解释编译? “机器语言”是纯二进制文件吗?

编辑:是的,计算机上的所有内容都是纯二进制文件。我询问处理器是否直接解释编译器输出的文件,或者操作系统是否先处理它?<​​/ p>

6 个答案:

答案 0 :(得分:16)

编译后的程序通常包含一个标题,后跟实际CPU指令(你可以称之为“二进制”)+各种其他数据。

当您尝试告诉操作系统加载程序时,操作系统将读取标头,并用于检查可执行文件是否真的是适用于此操作系统和此体系结构的可执行文件。即这样你就不会意外地在Windows或类似的程序上运行Linux程序。

标题还包含有关实际CPU指令在可执行文件中的位置的各种其他信息,其中包含数据段(文本,字符串,图形)等等。

一旦操作系统感到高兴,可执行文件就是它应该是的,那么操作系统会将可执行文件中的不同段加载到内存中,并指示CPU开始运行“二进制”代码段。从某种意义上说,这段代码是“纯粹的”,它是直接的CPU汇编代码。

然而,操作系统可以中断CPU(例如切换到另一个程序,或者只是从内存中杀死程序等等)。所以围绕这个正在运行的程序有很多事情,操作系统类型“管理”它并确保它的行为就像一个好男孩,但代码本身在运行时尽可能快地执行纯CPU指令..没有操作系统必须解释其间的代码。

另请注意,正在运行的程序可能会在运行时以各种方式调用操作系统。例如,要求操作系统在显示器上打开一个窗口,打开网络连接,分配内存等等。所有实际发生的事情是CPU只是跳转到在不同位置执行代码(即它从运行可执行文件中的代码跳转到在OS中运行一些代码,然后跳回)。

简而言之就是这样。还有很多其他方法可以运行程序。有虚拟机,解释型语言(例如Java或Ruby)等等。它们都以不同的方式运行程序,而不是传统的“纯二进制”语言,如C / C ++,但希望这有助于您了解它的工作原理。

答案 1 :(得分:3)

我认为你真正要问的是,编译的程序是否在裸机上运行(它们是否独立于操作系统执行)。非常简短的回答是,不。虽然程序本身确实执行本机CPU指令,但操作系统能够限制它并控制其行为。此外,在加载阶段,需要解析某些外部(dll)符号。最后,大多数程序依赖于各种操作系统抽象(例如,内存访问 - 编写自己的交换功能非常困难且毫无意义)。从这个意义上讲,没有二进制文件不是自主的裸机代码。

然而,他们纯二进制文件。计算机上的一切都是。

修改

解释您的问题的另一种方法是:编译程序实际上是本机CPU指令。答案是肯定的(除了加载二进制文件,操作系统必须提供帮助)。编译器输出汇编语言,其中每行对应一个CPU指令。这仍然是文字。程序集由汇编程序编译成实际的二进制文件。

答案 2 :(得分:2)

你是什么意思“真正的二元”?计算机中的所有数据都是1和0,尽管CPU根据内部门和晶体管的布局“解释”操作码。没有柏拉图式的二元语言理想。

答案 3 :(得分:0)

这样的应用程序通常被编译成机器代码,由处理器直接执行的指令:

http://en.wikipedia.org/wiki/Machine_code

x86 ASM是最常见的之一。把它想象成你的代码被编译成一种非常低级的语言。如果这就是你的意思,它就是一个只有1的层,而0是直接沿着金属发送的,并且操作系统仍然可以控制执行的内容。但是,是的,在一天结束时,一切都归结为二进制 - PC上的一切都可以做到!

答案 4 :(得分:0)

还应该考虑解释语言具有虚拟机代码。 (它仍然是二进制的。)它们被虚拟机(一类软件)变成机器代码。 (也是二进制。)

答案 5 :(得分:0)

我想知道为什么没有人提到链接器的概念。

基本上,编译器的输出实际上是一个二进制文件,但是有一个问题。此编译的二进制文件通常称为目标文件,其中包含目标代码。现在,不要在这里迷惑自己。 对象代码只是机器代码或您调用的二进制代码,但只是其中的一部分。编译器通常从单个程序的源输出多个这样的目标文件。基本上,这些目标文件中的每一个都包含该程序的完整可执行机器代码的一部分。这就是链接器的用武之地。它基本上将所有这些目标文件链接到一个完整的可执行文件,机器可以作为程序运行。