计算机本质的理解

数字编码 🔗︎

1. 计算机的本质 🔗︎

计算机本质是 0/1 的世界,如果要用 0/1 表达这个世界,结论是:需要通过 编码


2. 数字的表达方式 🔗︎

为什么会有补码? 🔗︎

  • 目的: 补码是为了方便计算机进行运算,尤其是加法。

  • 举例:
    计算 5 + (-3) 通过补码(定义:正数不变,负数取反并且+1)计算:

    • 步骤 1: 0101(5)
    • 步骤 2: 0011(3) -> 取反 1100 -> 加一 1101
    • 步骤 3: 0101 + 1101 = 100010 截断后为 0010(结果为 2)

    运算的结果符合人类的预期结果,而原码(首位为符号位)和反码(除了符号位,所有位取反)计算出来的结果都不满足人类预期。

为什么表示范围是 [-128, 127]? 🔗︎

  • 解释:
    以 4 位二进制补码为例:
    0000(-0) 0000(0)
    1111(-1)  0001(1)
    1110 (-2)  0010(2)
    ...
    1011(-5)   0101(5)
    1010(-6)   0110(6)
    1001(-7)   0111(7)
    
    范围是 [-7, 7],但 1000 没有被表示,刚好可以用来表示 -8-8 的补码表示:1000(原) -> 取反 0111 -> 加一 1000)。
    因此,最终范围是 [-8, 7]。同理,[-128, 127] 也解释得通。

为什么小数会有精度问题? 🔗︎

  • 原因: 在一些语言中,0.1 + 0.2 永远不会等于 0.3。因为二进制的小数只能用固定的数字组合,例如 0.2 无法用二进制精确表示。

文本编码 🔗︎

1. 编码的概念 🔗︎

  • 定义: 数字编码后,文本也需要通过编码来表示。
  • 实现方式: 编码主要通过 码表 实现,即字符和数字的对应关系。
    • 码表(字符集): 字符和数字的对应关系(接口)。
    • 字符编码: 具体实现。
    • 码点: 表中的每个数字(可能由一个或多个码元组成)。

2. 发展轨迹 🔗︎

  • ASCII: 英文和特殊字符,使用一个字节中的 7 位。

  • EASCII 字符集: ISO 8859-1。

  • GB2312: 早期汉字编码标准。

  • GBK: GBK 编码(汉字),扩展了 GB2312。

  • GB18030: 更全面的汉字编码标准。

  • Unicode 字符集:

    • 一般 Unicode 编码指 UTF-16 编码,变长编码、2 字节码元、有字节序问题。
    • UTF-8: 变长编码,单字节码元,无字节序问题。
  • 发展过程: 初始化 -> 本地化(GB 表示国标) -> 国际化 -> 效率化。


多媒体编码 🔗︎

1. 音频 🔗︎

  • 原理: 一定时间内采集有限的样本表示。
  • 采样率: 与模拟信号频率有关,例如每秒 40000 个样本。
  • 编码方式: AAC。

2. 图像 🔗︎

  • 光栅图:
    • 解析度: 单位面积像素数。
    • 色彩深度: 像素位数量。
  • 矢量图: 通过数学公式计算像素分布。

3. 视频 🔗︎

  • : 由图片构成,多帧构成视频流。
  • 编码方式: MPEG-1, MPEG-2, MPEG-4, H.264, H.265。

运算的本质 🔗︎

1. 概念 🔗︎

有了编码后,计算机如何实现计算?为什么内存条、芯片会很贵?

逻辑运算 🔗︎

  • 基本操作: 与、或、非、异或。
  • 实现方式: 通过逻辑门电路实现。输入是开关,输出一般是 LED 灯(有颜色的灯)。芯片一般是实现逻辑运算,例如 7486(异或门)芯片,会暴露一些引脚出来,比如一个接电源,一个接地,其他接输入,表示输出等。

2. 半加器 🔗︎

  • 定义: 不考虑进位的加法器。
  • 公式:
    • Cout = X * Y
    • S = X ⊕ Y

3. 全加器 🔗︎

  • 定义: 考虑进位的加法器。
  • 公式:
    S = X ⊕ Y ⊕ Cin
    Cout = (X * Y) + ((X ⊕ Y) * Cin)
    

4. 两位加法机 & 多位加法机 🔗︎

  • 两位加法机: 两个全加器串联。
  • 多位加法机: 多个全加器串联。

5. 记忆加法机 🔗︎

  • 功能: 保存上次计算的结果。

6. 选择加法机 🔗︎

  • 功能: 多弄几个记忆加法器,避免输错时重新来过。

7. 自动加法机 🔗︎

  • 功能: 按一下开关,自动输入并把所有数字加起来。

8. 自由加法机 🔗︎

  • 功能: 可控制只计算部分的数字。

9. 对比现代计算机 🔗︎

目前的计算机能进行 10 亿次的加法运算。计算机包含以下部分:

  1. 存储器: 存储箱,用于存储输入的数字、要执行的代码、计算的结果。
  2. 运算器: 累加器,计算两个数字相加。
  3. 控制器: 控制板,切换开关。
  4. 输入设备: 输入面板,输入开关。
  5. 输出设备: 输出灯泡,灯泡显示输出数据。

以上包含了:输入、输出、内存、寻址、译码、指令、算术逻辑单元等概念。


虚拟电路模拟 🔗︎


解释器和编译器的区别 🔗︎

1. 程序是如何运行的? 🔗︎

代码在执行前都需要通过语法解析器,将输入的代码字符串转换为 AST(抽象语法树)

解释器执行流程 🔗︎

  1. Lexer(词法分析器): 读取代码,将代码转换为 token 序列。
  2. Parser(语法分析器): 把读到的 Token 序列转换为 AST(大部分情况下 Lexer 是 Parser 的一部分)。
  3. Lowering/Desugar: 化简 AST 或者将语法糖的 AST 节点转换为标准等价 AST 节点。
  4. Interpreter: 递归执行 AST。

解释器直接解释执行 AST,并返回最终结果:

function interpret(ast) {
  switch (ast.type) {
    case "number":
      return ast.value;
    case "negative":
      return -interpret(ast.value);
    case "op":
      switch (ast.value) {
        case "+":
          return interpret(ast.v1) + interpret(ast.v2);
      }
  }
}

编译器执行流程 🔗︎

编译器将 AST 翻译成目标语言,例如汇编:

// 假定为目标机器为栈式虚拟机,然后通过 exec 函数执行
function compile(ast) {
  switch (ast.type) {
    case "number":
      return "ds.push(" + ast.value + ")\n";
    case "negative":
      return "ds.push(-ds.pop())\n";
    case "op":
      return (
        compile(ast.v1) +
        compile(ast.v2) +
        "ds.push(ds.pop() " +
        ast.value +
        " ds.pop())\n"
      );
  }
}

代码的本质 🔗︎

通过代码控制机器,代码是人阅读的指令。主要有两大要素:数据操作(判断、选择、循环、分支等)。


内存模型 🔗︎

1. 计算机是如何存储的? 🔗︎

运算的本质 中的锁存器(64 位构成的庞大数组),本质就是内存。

2. 执行过程 🔗︎

  • 顺序执行: 代码编译成一条条指令加载到内存(操作系统分配的执行区域),计数器逐步执行内存中的指令,返回结果。
  • 分支选择: 跳到对应地址执行指令。
  • 嵌套执行: 函数执行会在内存开辟一组连续的内存空间。函数代码执行前根据参数数量、参数大小,计算分配栈空间,栈底为内存高地址方向。

3. 活动记录 🔗︎

执行过程的活动记录由标记顶部位置的 帧指针 和标记底部位置的 栈指针 定义。当执行完毕,帧指针指向下一条指令地址。

当发布很酷的东西时,请第一时间通知我

订阅电子邮件,以获得我的最新文章。我不会向您发送垃圾邮件。随时取消订阅。