计算机程序/操作系统是否仅包含低级别的 X86-64 指令?

Ton*_*ony -2 assembly operating-system cpu-architecture machine-code low-level

对于一个新手/愚蠢的问题,我很抱歉,但这让我困扰了一段时间,而且似乎很难找到直接的答案。问题是关于计算机如何在低级别工作 - 更具体地说,是否有计算机可以执行的命令未包含在x86-64指令中。换句话说,您可能会问是仅使用 x86-64 指令编程的操作系统,并且操作系统运行的程序也是如此。请注意,我不是在询问特定于处理器的隐藏命令或附加命令,我们可能假设这些不存在。

提问的动机:

  • 通常的说法是编译器将特定语言的程序编译为机器码。但是,有许多命令不能(据我所知)仅使用 x86-64 指令用汇编语言编写。甚至像“malloc”这样简单的东西。所以看起来为操作系统编写的实际程序由机器代码和操作系统指令组成?

  • 如果查看 x86-64 指令集,似乎 I/O 命令(例如访问键盘、鼠标、硬盘驱动器、GPU、音频接口、时间、显示器、扬声器等)并没有针对它的所有命令,尽管可以使用 INT 命令来完成某些任务。根据这个答案“在现代体系结构上,外围设备的访问方式与内存类似:通过总线上的映射内存地址。”,无论在代码方面意味着什么。所以看起来甚至操作系统也不是只用 x86-64 指令编写的?

Pet*_*des 7

是的,CPU 只能运行机器代码(您可以通过 asm 1:1 表示)。对于某些语言,提前编译器将源代码转换为可执行文件中的机器代码。

对于其他人,例如 Java,通常将 JIT 编译为动态内存缓冲区中的机器代码,然后调用它。(进行 JIT 编译的代码最初是用 C 编写的,但在java可执行文件本身中提前编译为机器代码)。

在其他语言实现中,您只有一个解释器:它是一个程序(通常用 C 或 C++ 等预先编译的语言编写),它读取文件(例如 abashpython脚本)并解析它,决定其现有的哪个根据文件的内容使用什么参数调用的函数。运行的每条指令最初都在二进制文件中,但该解释器代码中有条件分支,这些分支取决于您运行它的文件中的高级语言代码。


malloc不是基本操作,它是一个库函数(编译为机器代码),它可能会进行一些系统调用(涉及在内核中运行一些机器代码)。

使用像 BOCHS 这样的全系统仿真器,您实际上可以通过任何程序单步执行机器指令,进入系统调用,甚至是中断处理程序。你永远不会发现 CPU 执行任何非机器代码指令;这实际上是它的逻辑电路在从内存中提取后知道如何解码的唯一东西。(能够被 CPU 解码是使它成为机器代码的原因)。

机器代码总是由一系列指令组成,每个 ISA 都有一种汇编语言,我们可以用它来表示机器代码的人类可读性。(相关:当我们有编译器时,为什么我们甚至需要汇编程序? re:汇编语言的存在而不仅仅是机器代码)。

此外,任何给定 ISA 的指令格式至少在某种程度上是一致的。在 x86-64 上,它是操作码、操作数(modrm + 可选的其他字节)和可选的立即数的字节流。(还有前缀... x86-64 有点乱。)在 AArch64 上,机器指令是固定宽度的 4 字节,在 4 字节边界上对齐。

“在现代架构中,外围设备的访问方式与内存类似:通过总线上的映射内存地址。”

这意味着执行像 x86-64 这样的存储指令mov [rdi], eax将 4 个字节存储到地址=RDI 处的内存中。CPU(或旧系统中的北桥)内部的逻辑根据地址而不是指令来决定给定的物理地址是 DRAM 还是 I/O。

或者 x86-64 有访问 I/O 空间(与内存空间分开)的指令,比如inout


回复:新标题:

计算机程序/操作系统是否仅包含低级别的 x86-64 指令?

不,大多数程序和操作系统还包含一些静态读写数据 ( .data) 和只读常量(一个.rodata部分),而不是仅将常量作为立即操作数的代码。

但是当然数据不会“运行”,所以也许这不是您的意思。所以是的,除非你想用固件玩语义。

一些现代 I/O 设备的驱动程序需要固件二进制 blob(其中一部分是嵌入在 GPU、声卡或其他任何东西中的微控制器的机器代码)。

从操作系统的角度来看,这只是它必须发送到 PCIe 设备的二进制数据,然后它才能按照其文档所说的方式响应 MMIO 操作。对于操作系统来说,非 CPU 设备如何在内部使用该数据并不重要,无论它实际上是微控制器的指令,还是只是声卡 MIDI 合成器的查找表和样本。