11

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

编辑:是的,计算机上的一切都是纯二进制的。我问处理器是直接解释编译器输出的文件还是操作系统先处理它?

4

6 回答 6

20

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

当你试图告诉操作系统加载你的程序时,头文件将被操作系统读取,它用于检查可执行文件是否真的是一个适用于这个操作系统和这个架构的可执行文件。即,这样您就不会意外地在 Windows 或类似设备上运行 Linux 程序。

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

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

然而,操作系统仍然可以中断 CPU(例如切换到另一个程序,或者只是从内存中终止程序等等)。所以围绕这个正在运行的程序发生了很多事情,操作系统会“管理”它并确保它表现得像个好孩子,但代码本身在运行时正在尽可能快地执行纯 CPU 指令..无需操作系统解释其间的代码。

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

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

于 2011-07-27T01:54:44.053 回答
3

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

但是它们纯二进制的。计算机上的一切都是。

编辑

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

于 2011-07-27T01:21:51.100 回答
2

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

于 2011-07-27T01:20:27.863 回答
0

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

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

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

于 2011-07-27T01:19:47.947 回答
0

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

于 2011-07-27T01:27:52.277 回答
0

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

基本上,编译器的输出实际上是一个二进制文件,但有一个问题。这个编译的二进制文件通常被称为包含目标代码的目标文件。现在,不要在这里混淆自己。目标代码只不过是您所说的机器代码或二进制代码,但只是其中的一部分。编译器通常会从单个程序的源中输出多个这样的目标文件。所以本质上,这些目标文件中的每一个都包含该程序的完整可执行机器代码的一部分。这就是链接器发挥作用的地方。它基本上将所有这些目标文件链接成一个完整的可执行文件机器可以作为程序运行。

于 2014-01-21T14:07:16.830 回答