汇编

一、汇编在计算机系统中的位置(第一性原理)

1.1 汇编的本质

汇编语言是指令集体系结构(ISA)的符号化表示。

它处在三个世界的交汇点:

汇编不是“更底层的 C”,而是程序执行模型的显式展开


1.2 汇编存在的根本原因

从系统视角看,汇编解决三个不可回避的问题:

  1. **状态必须被显式管理**(寄存器 / 内存 / 标志位)
  2. **控制流必须被离散化**(跳转而非抽象语句)
  3. **资源是有限且共享的**(寄存器数量、调用约定)

因此:


二、程序执行的统一状态模型

所有汇编程序,本质上都是在操作一个有限状态机

2.1 程序的核心状态

一个正在运行的程序,只由以下状态完全刻画:

  1. **程序计数器(PC)**:下一条将执行的指令地址
  2. **寄存器文件**:当前可快速访问的计算状态
  3. **内存**:持久化的程序与数据存储
  4. **条件码(FLAGS)**:最近一次计算的逻辑结果

汇编语言的所有指令,都是在读取或修改上述状态


2.2 通用寄存器模型(以 x86-64 为例)

不变原理:

⚠️ 具体寄存器命名(%rax / %rbx …)是 x86 特有的,不可迁移


三、数据如何被表示与访问(状态读取规则)

3.1 数据宽度与类型消失

在汇编层面:

位宽语义层常见映射
8char / byte
16short
32int / float
64long / pointer / double

类型检查在编译期结束,运行期只剩位模式。


3.2 操作数与寻址的统一抽象

所有指令操作数,本质只有三类:

  1. **立即数**:常量嵌入指令
  2. **寄存器**:CPU 内部状态
  3. **内存引用**:通过地址计算得到的外部状态

x86-64 提供了高度灵活的地址计算形式:

Mem[ base + index * scale + displacement ]

不变原理:


四、状态如何发生变化(运算与传送)

4.1 数据传送是最基本的状态变换

mov 类指令完成:

⚠️ 内存 ← 内存 永远不允许

这是所有主流 ISA 的共性约束。


4.2 扩展不是类型转换,而是位模式解释

不变原理:


4.3 算术与逻辑操作的统一视角

算术 / 逻辑指令做两件事:

  1. 修改目标操作数
  2. **隐式更新条件码**

条件码是后续控制流决策的唯一依据。


五、控制流:从顺序执行到分支与循环

5.1 条件码是控制流的中介状态

控制流 = 计算结果 → 条件码 → PC 更新


5.2 分支的两种实现策略

  1. 显式跳转(jmp / jcc)

    • 易理解
    • 易产生分支预测失败
  2. 条件传送(cmov)

    • 消除控制依赖
    • 用数据依赖换性能稳定性

不变原理:


六、过程抽象:函数调用为何必须使用栈

6.1 函数调用的三大本质需求

  1. **控制转移**(返回地址)
  2. **状态隔离**(局部变量)
  3. **资源复用**(寄存器、内存)

栈是一种天然满足“后进先出调用关系”的数据结构。


6.2 调用约定的存在理由

调用约定解决:

不变原理:

调用约定的目标不是效率,而是模块可组合性


6.3 栈帧是时间序列的空间映射

这与 JVM / Python 虚拟机的栈模型在本质上完全一致。


七、数据结构的底层本质:地址与偏移

7.1 数组、结构体、联合的统一解释

所谓“复杂数据结构”,在汇编中只剩下地址计算


7.2 对齐的真实目的

对齐是体系结构与编译器的协商结果。


八、浮点与向量:并行数据通路的体现

8.1 浮点寄存器的本质

SIMD 的目标是:

用一次指令,处理多份独立数据


8.2 浮点运算的关键限制

这是因为浮点单元与整数单元的硬件实现不同。


九、哪些知识是稳定的,哪些不是

9.1 长期可迁移的认知

9.2 易变的实现细节

关联内容(自动生成)