%%
# 纲要
> 主干纲要、Hint/线索/路标
# Q&A
#### 已明确
![[02-开发笔记/03-计算机基础/计算机基础#^krybvf]]
#### 待明确
> 当下仍存有的疑惑
**❓<font color="#c0504d"> 有什么问题?</font>**
# Buffer
## 闪念
> sudden idea
## 候选资料
> Read it later
# 正文
![[_attachment/02-开发笔记/03-计算机基础/计算机基础.assets/IMG-计算机基础-6E9DFE77165EAE78DAD45D6787326D70.png|564]]
%%
# 计算机中的基本单位—比特/字节/字长
## 比特位 bit
**比特** bit 是 **==数据量==** 的基本单位,也即计算机中的 "**最小信息单元**",
**网络带宽和传输速度一般用 bit 进行衡量**。
**网络传输速率、宽带速率、路由器速率**的单位都是 **bps(比特每秒)**,例如 **100 兆宽带为 100M bps**。
## 字节 byte
- **字节** byte 是**计算机中==数据存储的最小单位==(存储单元)**,计算机**存储空间和内存大小**都**使用 byte 衡量**。
- **一个字节**由 **8 位(bit)** 组成,每位是一个二进制数 0 或 1。
- 一个字节可以表示 $2^8=256$ 种不同的值,范围为 $[0, 255]$。
- **字节** byte 也是 **==最小的可寻址内存单位==**(Addressable Unit):
- 从逻辑上来说,**内存**被视为一个**连续的字节数组**,称之为"**==虚拟内存==**",其中**每个字节都有其==唯一的地址==标识**(数组索引),这些**内存地址从 0 开始**,所有**可能地址的集合**即称之为 "**==虚拟地址空间==**"。
##### 常用单位换算
| 单位 | 等价的小一级单位 | 等价的字节 |
| --- | -------- | ---------- |
| PB | 1024 TB | $2^{50}$ B |
| TB | 1024 GB | $2^{40}$ B |
| GB | 1024 MB | $2^{30}$ B |
| MB | 1024 KB | $2^{20}$ B |
| KB | 1024 B | $2^{10}$ B |
<br>
## 字长 Word size
**==字长==(word size)** 是计算机系统的一个基本参数,表示**计算机 CPU ==一次性能够处理的最大数据位数==(bit)**,也即 "**CPU 内数据通路的宽度**"。
字长代表了**两项重要指标**:
- **数据处理能力**:字长表示 **==CPU 在单个操作周期可以处理的最大数据位数==**。
- 一个 32 位处理器可以一次处理**32 位(4 字节)** 的数据
- 一个 64 位处理器可以一次处理**64 位(8 字节)** 的数据
- **内存寻址能力**:字长决定了 **==计算机系统 "虚拟地址空间" 的最大范围==**,也即 **CPU 的可寻址范围**。
- "**虚拟地址**" 采用 **==一个字长==** 进行编码,对于一个**字长为 $w$ 位的机器**,可表示的**虚拟地址范围为 $0\sim 2^w-1$**,因此程序最多可访问 **$2^w$ 个字节**:
- 32 位系统最多只能直接寻址到 **4GB 的内存空间**,**虚拟地址范围是 $0 \sim 2^{32}-1$** ;
- 64 位系统理论上可以寻址到 **16EB 的内存空间**,**虚拟地址范围是 $0 \sim 2^{64}-1$** 。
大多数 64 位机器也能运行 32 位机器编译的程序,这是一种向后兼容。
> [!caution] 「**字长**」并非是 「**字**」的长度!两个概念彼此独立,没有关联
>
> 字长是 "**CPU 内数据通路的宽度**":
>
> ![[_attachment/02-开发笔记/03-计算机基础/计算机基础.assets/IMG-计算机基础-C0EDCEC11AFDD5146B7E818D816183E9.png|477]]
>
<br>
## 字 Word
x86 体系结构中,用术语 "**字"**(word) 表示 **==2 字节== 16 位**的**数据类型**。
- **双字**(DWORD,也称 long WORD):**4 字节 32 位**
- **四字**(QWROD):**8 字节 64 位**
![[_attachment/02-开发笔记/03-计算机基础/计算机基础.assets/IMG-计算机基础-A4F29B98B40F32CDD196B669E729684C.png|578]]
<br><br><br>
# 多字节数据的地址及存储方式——大端模式与小端模式
> [!NOTE] LSB 和 MSB
>
> - **最低有效字节**(Least Significant Byte,**LSB**)
> - **最高有效字节**(Most Significant Byte,**MSB**)
计算机中,"**==多字节数据的地址==**" 取的是**其占用的 "==最小地址=="**。
(在大端模式下,即 MSB 所在的地址;在小端模式下,即 LSB 所在的地址)
**多字节数据在内存中的 "==存储顺序=="** (也称 "**==字节序==**")则有两种不同方式:
- **大端模式**(Big Endian): 数据的 **==高位==字节**存储在**内存的==低地址==** 上
- **小端模式**(Littel Endian):数据的 **==低位==字节**存储在**内存的==低地址==** 上
- 即**数据的低位字节对应低地址**,**高字节对应高地址**
![[_attachment/02-开发笔记/03-计算机基础/计算机基础.assets/IMG-计算机基础-C2A4578626D39B509C941904038D38D5.png|645]]
实际应用:
- 在**指令集架构**中:
- 在 **Intel x86、x86-64** 架构中,采用 **==小端模式==**;
- 许多**RISC 架构**(如 PowerPC)默认采用**大端模式**;
- 在**网络协议**中,通常采用**大端模式**(也称**网络字节序**);
- 在**图片格式**存储中:
- GIF 是小端模式,JPEG 则是大端模式
> [!NOTE] 小端法字节序书写
>
> 小端法**书写字节序列的自然方式是==最低位字节在左边==,==最高位字节在右边==**(与常规数字书写正好相反)
>
> 例如 `0x200b43` 这一数据的**字节序**应该写为 `43 0b 20 00`。
>
> 对多字节数据的读取即**从低地址开始**,**读取得到数据的最低位字节**,再往后。
<br>
## 如何判断系统的字节序?
> <font color="#c0504d">❓如何判断系统是大端模式还是小端模式?</font> ^krybvf
存一个**多字节数据**,从其**最低地址起**,**逐字节地访问该数据的内存表示**,从而判断:
```cpp
#include <iostream>
using namespace std;
int main(int argc, char** argv) {
// int: 4字节32位, 赋值为1
unsigned int x = 1;
// 将int的地址int*p类型强制转换为unsigned char*类型, 即指向单字节的指针
unsigned char* bytePtr = reinterpret_cast<unsigned char*>(&x);
// bytePtr指向的是int型占有的"最低地址", 检查该地址的值是否为1
// 若是1, 则为小端模式(低字节在低地址). 反之, 为大端模式
cout << (int) *bytePtr << endl;
// cout << (int) bytePtr[0] << endl; // 与上等价
return 0;
}
```
<br><br><br>
# 计算机语言
计算机语言包含三层(由**最底层/机器可读**=> **高层抽象/人类可读**):
- **机器语言**(机器指令):最底层的二进制码,直接控制硬件
- **汇编语言**(汇编指令):机器语言的符号化表示,人类易读;
- **高级程序语言**(C、C++、Java、Python 等):提供高度抽象、硬件无关的编程语言,供人类编程。
![[_attachment/02-开发笔记/03-计算机基础/计算机基础.assets/IMG-计算机基础-3E334F21E31D30C225E5C58DB78EC0A7.png|215]]
汇编语言是对机器语言的文本表示,当使用**汇编语言**编程时,程序员**必须指定 CPU 所需执行的具体指令**。
而**高级程序语言**则提供了较高的抽象,**屏蔽了机器(处理器)的执行细节**。
<br>
## 机器语言 Machine Language
**机器语言**(也称**机器指令**、**机器码**)是计算机唯一能够**理解和执行的指令**,由**纯粹的==二进制码== 0/1 序列**构成。
**机器指令直接控制计算机==硬件==执行基本操作**,例如执行加法、数据移动、跳转等。
不同的**指令集架构(ISA)** 下所定义的机器指令不同,无法跨平台使用。
> [!example]
>
> 例如二进制指令 `10110000 01100001` 的含义取决于具体的**指令集架构**,在某些处理器上,它可能表示将值`0x61`(十六进制)加载到寄存器。
>
> [!NOTE] 理解 "机器视角"
>
> 从机器的角度来看,**程序与数据都仅仅只是由二进制码 0/1 构成的字节序列**。
>
> **不同的机器类型**通常具有**不同且不兼容的指令集架构 ISA**,同时**不同的操作系统**也会有**不同的编码规则**,
>
> 因此,**==编译后的二进制代码==很少能够"直接"在不同机器和操作系统组合之间进行移植**。
<br>
## 汇编语言 Assembly Language
**汇编语言**(也称**汇编指令**)是一种低级程序语言,使用**符号化的指令**(助记符)和**操作码**来表示机器指令,人类易读,但需要由 **==汇编器==(Assembler)** 将其翻译为机器语言以供计算机执行。
![[_attachment/02-开发笔记/03-计算机基础/计算机基础.assets/IMG-计算机基础-04D152B424C7BB270B1E481019711434.png|568]]
实际上,「**汇编语言**」包含三类指令:
- **汇编指令**:机器指令的文本助记符,每一条**汇编指令**通常对应一条**机器指令**。
- **伪指令**:没有对应的机器码,**由编译器执行**,计算机并不执行
- **其他符号**:如 `+,-,*,/` 等,**由编译器识别**,没有对应的机器码。
> [!example]
>
> x86 汇编语言 `MOV AL, 61h` 表示将十六进制值 `61` 加载到寄存器 `AL` 中,
> 对应的机器语言指令可能即为 `10110000 01100001`
<br>
## 高级程序语言
提供**较高抽象层次**的编程语言,硬件无关,**人类易读**且提供了更多、更灵活、更强大的功能特性。
**高级程序语言编写的源代码**需要最终转换为**机器指令**,才能供计算机执行,通常由两种方式:
- (1)由 **==编译器==(compiler)** 编译为**汇编语言**,再由 **==汇编器==**(Assembler)转换为**机器指令**;
- 例如 C,C++语言
- (2)由 **==解释器==(interpreter)** 编译为**字节码**,再由特定工具**将字节码解释为机器指令**。
- 例如 Java,Python 语言
> [!NOTE] 「**字节码**」
>
> 「字节码」是高级程序语言与机器语言之间的一种**中间表示**,**既不是高级语言代码,也不是汇编语言或机器语言**。不同语言中的 "字节码" 各不相同。
<br><br>
### 源代码到机器指令的转换
###### C/C++ 源代码的转换过程
参见[[02-开发笔记/03-计算机基础/编译与链接/编译与链接|编译与链接]]
###### Java 源代码的转换过程
- Java 源代码保存为 `.java` 文件;
- **Java 编译器**(`javac`)将 Java 源代码编译为**字节码**,存储在`.class`文件中。
- **Java 虚拟机**(JVM)将字节码解释为 "**机器指令**",生成**二进制可执行文件**
Java 字节码是平台无关的,**在任何安装了 JVM 的系统上都能运行**,因此 Java 非常适用于跨平台开发。
> [!NOTE] **Java 的字节码**可以视为 "**==虚拟机`JVM` 的机器指令==**"(正如其名,"**虚拟机器**"),再由 `JVM` 翻译为**平台特定的机器指令**。
###### Python 源代码的转换过程
- Python 源代码保存为 `.py` 文件
- **Python 解释器** 将 python 源代码翻译为**字节码**(通常可能只在内存中生成而不会产生文件)
- 字节码文件后缀为 `.pyc`,通常存储在源代码同目录下的 `__pycache__/` 目录中。
- **Python 解释器** 再将字节码逐句解释为 "**机器指令**",**直接执行**(不生成可执行文件)
#### 编译型语言与解释型语言
- **编译型**语言:**源代码需要先编译生成 "==二进制可执行文件=="(机器级目标程序)再运行
- 特点:
- **编译过程可进行全面的语法和语义检查**;
- **编译生成的可执行文件**通常**与特定的硬件和操作系统相关**,不具有可移植性。<br>要在不同的平台上运行,需要重新编译源代码。
- **编译后的程序可直接执行,通常具有较高的执行速度**
- 典型代表:C、C++、Go、Rust、Java
- **解释型**语言:**不需要编译为可执行文件**,源代码**由解释器==逐行翻译为机器指令==并立即执行
- 特点:
- **每次运行代码都需要解释器参与**,逐行翻译解析,因此**运行速度较慢**。
- **代码在执行时才被翻译和检查,许多错误只有在运行时才能发现**
- **平台无关**——**可在安装了解释器的任何平台上运行**
- 典型代表:Python、JavaScript、Ruby、Shell
> [!NOTE]
>
> 一些现代编程语言(如Java、Python)**实际上采用了混合模式**,既有编译步骤也有解释步骤,
> 但主要根据是否会 "**==生成二进制可执行文件==**" 来区分。
>
> - Java 先将源代码编译成字节码,然后由JVM解释或JIT编译执行;
> - Python 先将源代码编译成字节码,然后由解释器执行字节码。
<br><br><br>
# 指令集架构 ISA
> **指令集架构**(Instruction Set Architecture, ISA),也称**指令集体系结构**;
![[_attachment/02-开发笔记/03-计算机基础/计算机基础.assets/IMG-计算机基础-E6FF34E5BF647CA269A3B9725E37810F.png|842]]
**指令集架构(ISA)** 是一套**关于计算机处理器 CPU 的标准**——**==CPU 向软件提供的、操作 CPU 的接口==(即各种机器指令)**
ISA 定义了 CPU 支持的**指令集**、**指令格式**、**数据类型与格式**、**寄存器**、**内存寻址方式**、**中断及异常处理机制**、**与 I/O 设备间的通信机制**等,提供了**处理器与软件(包括 OS )之间的 "二进制接口" (ABI)**。
- **指令集**:
- 定义了处理器可以执行的 **==所有指令的集合==**,包括**数据处理指令**(如加法、减法),**数据传输指令**(如加载、存储),**控制流指令**(如跳转、分支)等。
- ![[_attachment/02-开发笔记/03-计算机基础/计算机基础.assets/IMG-计算机基础-AAF21B259B593792FEC6738CA161D23F.png|535]]
- ISA 规定了每条指令的操作数、操作数位置、操作数类型。
- **指令格式**:
- 定义了每条指令的二进制机器语言表示
- 包括操作码(opcode)、操作数字段、地址模式等。
- **数据类型和格式**:
- 规定了处理器可以**直接处理的操作数的类型,如整数、浮点数、字符**等,
- 规定了这些数据**在内存中的表示方式和存储方式**
- **寄存器**:
- 定义了**处理器内部的寄存器的名称、编号、大小和用途**。
- 寄存器可以是通用寄存器、浮点寄存器、专用寄存器(如程序计数器、状态寄存器)等。
- **内存方面**:
- 规定了**操作数**在内存空间中的存放方式(大端/小端模式)
- 规定了处理器**如何寻址内存**,包括**内存地址的大小、内存寻址方式**(如直接寻址、间接寻址、基址加偏移寻址)等。
- **中断和异常处理**:
- 定义处理器如何响应和处理中断和异常,包括中断向量、优先级、处理流程等。
- **I/O机制**:
- 规定处理器与输入输出设备之间的接口和通信方式。
> [!NOTE] ISA 是 CPU 与软件(包括操作系统)之间的接口
>
> 在同一指令集架构下,不同的 CPU 型号与不同操作系统之间均能适配。
>
> 例如 64 位的 Window 或 Linux 系统基于 x86-64 架构,能够运行在任何基于同一架构的 CPU 之上。
![[_attachment/02-开发笔记/03-计算机基础/计算机基础.assets/IMG-计算机基础-8237B479CCEA5AB9E815BA9CF49E1326.png|512]]
<br><br>
## 「精简指令集 RISC」 与 「复杂指令集 CISC」
CISC 和 RISC 是两种不同的 **ISA 设计理念**:
- **复杂指令集**(CISC, Complex Instruction Set Computer)
- **精简指令集**(RISC, Reduced Instruction Set Computer)
##### 精简指令集(RISC)
RISC 强调 **==简化==指令集的复杂性**,使用更少、更简单的指令来执行程序
代表架构:**ARM**、**MIPS**、**RISC-V** 等
特点:
- **指令数量少且简单**:RISC 指令集包含较少的指令,每条指令执行的操作简单而快速。
- **固定指令长度**:所有指令通常具有相同的长度,简化了指令解码和执行的过程。
- **单周期指令执行**:大多数指令在一个时钟周期内完成,提升了指令执行的速度。
- **大量通用寄存器**:RISC 架构通常提供更多的寄存器,以减少内存访问次数,提高操作效率。
- **Load/Store 架构**:只有加载(Load)和存储(Store)指令访问内存,其余指令只在寄存器之间操作,减少了内存访问的复杂性。
- **简化的寻址模式**:RISC 架构使用简单的寻址模式,使得指令的解码和执行更加高效。
##### 复杂指令集(CISC)
CISC 强调**指令集的多样性和复杂性**,使用较多、较复杂的指令来执行程序。
代表架构:**x86**(Intel、AMD)、VAX、IBM System/360 等。
特点:
- **指令数量多且复杂**:CISC 指令集包含大量指令,每条指令可以执行复杂的操作,可能涉及多个时钟周期。
- **可变指令长度**:指令长度不固定,根据操作的复杂性而变化。
- **多周期指令执行**:许多指令需要多个时钟周期才能完成,指令执行时间不固定。
- **较少通用寄存器**:CISC 架构通常提供较少的寄存器,更多地依赖内存访问。
- **内存到内存操作**:指令可以直接在内存位置之间操作,不需要先加载到寄存器。
- **丰富的寻址模式**:CISC 架构支持多种复杂的寻址模式,使得指令可以直接访问复杂的数据结构。
<br>
## 常见的指令集架构
- **x86 架构**:
- 由 Intel 和 AMD 等公司广泛使用的**复杂指令集计算(CISC)架构**,广泛应用于个人计算机和服务器
- **ARM 架构**:
- 由 Arm公司设计的**精简指令集计算(RISC)架构**,广泛应用于移动设备、嵌入式系统和物联网设备。
- **RISC-V 架构**:
- 一种**开源的RISC架构**,受到学术界和工业界的广泛关注和支持
- **MIPS 架构**:
- 一种经典的RISC架构,广泛应用于教育和嵌入式系统。
![[_attachment/02-开发笔记/03-计算机基础/计算机基础.assets/IMG-计算机基础-E523A9234C0EFA71620628AD570E0E54.png|730]]
<br>
## 关于 x86 与 x86-64 架构
- **x86 架构**(也称 x86-32、**Intel 32**、**IA-32**):**32 位的体系结构**
- **x86-64 架构**(也称 x64、**AMD-64**、Intel 64):**64 位的体系结构**(基于 x86 的 64 位扩展)
64 位指令集可以运行 64 位数据指令,针对的是 64 位的 CPU(即**CPU 一次可提取 64 位数据**)
64 位 CPU 中**通用寄存器**(General-Purpose Registers,GPRs ) 的**数据宽度为 64 位**。
> [!info] 历史由来[^1]
>
> - **x86 也称 IA-32**(Intel Architecture 32bit),是由英特尔公司于 1985 年最早推出的。
> - IA-64 是由英特尔与惠普公司曾经联合推出的 64 位指令集,**不兼容 x86**,导致市场惨淡被淘汰
> - **x86-64 也称 AMD-64**,是由 AMD 公司发明的基于 x86 架构的 64 位扩展。
>
>
> [!info] x86-64 是现代 CPU 最主流的架构。
>
> 现代操作系统基本都已经淘汰了 32 位版本,通常都是**64 位系统**,也就是针对 x86-64 架构的系统版本。
>
> - **Windows 系统**:Windows Vista, Windows 7, Windows 8/8.1, Windows 10, 和 Windows 11 都有 x86-64 版本。
>
> - **Linux 系统**:几乎所有主流的 Linux 发行版都支持 x86-64 架构。
<br><br><br>
# API 与 ABI
操作系统提供的接口包括两种:API 与 ABI
- **应用程序==编程接口==** **API**(Application Programming Interface)
- **应用程序==二进制接口== ABI**(Application Binary Interface)
> [!example]
>
> - C 标准库中的 `mmap`、`munmap`、`malloc`、`free` 接口是**面向 C 语言编程提供的,源代码层面的接口**,属于 API。
> - C 标准库在实现这些接口时使用的 `mmap`、`munmap`、`brk`、`sbrk` **==系统调用==** 属于 ABI。
### API
API 是**源代码/语言级别的**,供高级编程语言**编写应用程序时调用**,是**源代码层面使用的接口**。
**操作系统提供的 API** (例如 Linux 系统库 Glibc)定义了操作系统所提供的特定功能和服务,如文件操作、内存管理、硬件访问等。
API 接口通常由语言自身的标准库提供,例如 C 标准库中包含的 `mmap`、`munmap`、`malloc`、`free` 等函数 API,提供了与操作系统的交互。
> [!NOTE] Unix/类 Unix 系统的 **POSIX 标准**、**UNIX System V 标准**、**Unix BSD 标准** 都属于 API。
### ABI
ABI **二进制==机器指令==层面的接口**,定义了**应用程序的二进制文件(可执行文件)如何与操作系统进行交互**,从而在特定操作系统和硬件上运行。
ABI 定义了**二进制接口规范**,包括**二进制文件格式**(例如 Linux 下的 ELF 格式与 Windows 下的 EXE 文件格式)、**数据模式**(大端模式与小端模式)、**数据结构**、**寄存器的使用方式**,以及**调用和返回约定**(参数传递与返回值处理),受**机器硬件、操作系统、编译器、链接器**等多种因素的影响。
> [!NOTE] ABI 的影响因素 [^2]
>
> ![[_attachment/02-开发笔记/03-计算机基础/计算机基础.assets/IMG-计算机基础-14622F15FA4B271BD391436613B4B5F5.png|503]]
<br><br>
# 参考资料
# Footnotes
[^1]: [X86、X64和X86\_64区别](http://www.360doc.com/content/19/0828/10/19244573_857512066.shtml)
[^2]: 《程序员的自我修养:链接、装载与库》