assembly - 当一段代码被编译和运行时,计算机内部会发生什么
问题描述
我很好奇如何将一段代码转换为计算机可以理解的东西。在许多类似的问题中,一个常见的答案是说明从人类可读代码到机器级指令的链或多或少遵循编译链:
high-level code --> assembly code --> machine binary code
尽管如此,这个答案的频率很高,对我来说计算机中到底发生了什么仍然有点神秘。我确实在一定程度上了解计算机和 CPU 背后的基本电子设备,但这种特殊情况对我来说仍然有点神秘。
例如,我编写了经典的“Hello, world!”。例如在
#include <iostream>
using namespace std;
int main()
{
cout << "Hello, world!";
return 0;
}
然后将其转换为汇编代码,例如
section .text
global _start ;must be declared for linker (ld)
_start: ;tell linker entry point
mov edx,len ;message length
mov ecx,msg ;message to write
mov ebx,1 ;file descriptor (stdout)
mov eax,4 ;system call number (sys_write)
int 0x80 ;call kernel
mov eax,1 ;system call number (sys_exit)
int 0x80 ;call kernel
section .data
msg db 'Hello, world!',0xa ;our dear string
len equ $ - msg ;length of our dear string
最终转化为二进制序列
10100010101001111...................
然后“你好,世界!” 出现在屏幕上。
因此我的问题是:在这个过程中,在计算机内部这个过程的每个阶段发生的电信号电平是什么?
我知道我的问题可能过于宽泛而无法完全回答,因此如果您能指出计算机内部发生的主要物理现象(例如硬盘驱动器、CPU 和 RAM 之间),我将不胜感激。
另外,如果我的问题离题,请告诉我,因为计算机工程不同学科之间的边界并不总是 100% 明确。在这种情况下,您能否建议另一个 SE 站点,该站点可能更适合此问题,谢谢。
解决方案
计算机具有 CPU 和 RAM 以及可以连接的设备。
编译器将程序(源)代码翻译成机器代码,其中程序代码和数据被编码为数字——另请参见指令集架构。
操作系统将机器代码加载(参见loader)到进程中,并在开始时启动 CPU。
CPU是将数字解释为机器代码指令的硬件,这些指令告诉它机器代码程序的每一步要做什么,以及在每一步,下一条机器代码指令应该是什么。
一些机器代码指令告诉计算机在内存中加载或存储数据,或者与设备通信。还有一种中断机制可以让设备引起 CPU 的注意。
这个过程非常元,因为 CPU 在编译、链接和运行操作系统期间对机器代码进行相同的解释——有诸如上下文切换之类的机制允许 CPU 切换作业/程序并扮演不同的角色(操作系统,用户进程A,B等)。除了空闲时,CPU 总是在执行一些程序,即作为机器代码指令的一些编程步骤序列。
晶体管实现 CPU 和 RAM。CPU内部有一些功能单元,例如加法、减法、条件分支等。这些功能单元由大量的晶体管组成。CPU 还具有寄存器存储器和高速缓存。它们都根据当前正在执行的机器代码指令切换值,因为 CPU 的唯一工作是在指令之后执行机器代码指令。
例如,假设机器代码程序指示计算机将恰好位于 CPU 寄存器中的两个数字相加,然后将答案写回其中一个。硬件将首先获取要执行的指令,然后解码其中的数字,从命名寄存器中提取值,将这些值提供给 ALU 的输入,指示 ALU 执行加法,然后将 ALU 的输出存储回寄存器— 为下一条机器代码指令做好准备。
我们还知道,可以通过晶体管可以执行的许多非常简单的布尔逻辑来执行加法,请参见加法器。处理器的所有功能都采用了这种将晶体管组装成 CPU 解释机器代码指令所需的功能单元的相同想法。
大多数数字电路都是使用一种单一的门构建的,即今天的与非门。可以安排门来实现任何布尔函数。这些晶体管排列成两大类电路:组合电路和顺序电路。组合电路仅根据提供的输入计算输出值,而时序电路具有反馈回路,使它们能够记住事物。设计者交替组合电路和时序电路来构成 CPU 的功能单元。为简化起见,寄存器和存储器是使用顺序逻辑制成的,而 ALU 将使用组合逻辑。
您还可以查看RAM,以及它是如何由晶体管构成的。
我们还可以注意到,在执行任何给定的机器代码指令集期间,一些电路未使用,因此我们不关心这些晶体管是否翻转或翻转,除非试图节省电力;其他晶体管预计会简单地保持其状态,例如当前机器代码指令中不涉及的寄存器和 RAM。
推荐阅读
- ios - SWIFT如何使UIButton的右侧先出现然后左侧
- c# - RxJs 一个请求
- sql - 使用范围内的日期来连接和显示所有日期?
- formula - DAX - 使用过滤器进行总结
- uuid - 我的 MAC 地址与远程生成的版本 1 UUID 中的 MAC 值不匹配
- javascript - Owl carousel 2 导航控件被隐藏和禁用
- javascript - 尝试在 React 中进行排序和切片时,如何保留整个 geojson?
- mysql - Case语句中的MySQL AND语句?
- android - 暂停和恢复用于下载文件的协程
- python - Jupyter Notebook 在 Anaconda Prompt for Qiskit 中的命令失败