解构汇编, 万物起源

发布于:2025-09-08 ⋅ 阅读:(16) ⋅ 点赞:(0)

汇编的诞生

  • 机器语言的困境
    • 早期的程序员直接使用机器语言进行编程
    • 机器语言由纯粹的数字(0, 1) 组成, 对应着CPU可以直接执行的指令和数据
    • 繁琐, 反人类, 难以记忆
  • 汇编语言的诞生
    • 为了解决上述问题, 人们发明了汇编语言(Assembly Language)
    • 核心思想: 为那些晦涩的二进制机器指令起一个简单易记的英文缩写, 助记符(Mnemonic)
    • 例如:
      • ADD 代表 加法 操作
      • MOV 代表 移动 数据
    • 10110000 01100001 -> MOV AL, 97 大大提高编程效率和可读性
  • 汇编器的作用
    • CPU只能理解二进制机器码, 看不懂 MOV AL, 97 这样的指令
    • 汇编器被创造: 将汇编语言写的源代码汇编(翻译)成机器语言目标代码

汇编全景图

[图片]

核心主干: CPU架构

汇编语言不是一种标准化的语言, 不同的CPU架构有不同的指令集, 因此有完全不同的汇编语言.

  • x86/x86-64 (CISC 复杂指令集)
    • 领地: Windows, Linux.
    • 特点: 历史悠久, 指令集庞大且复杂, 变长指令, 寄存器数量小但功能强大
    • 厂商: Inter 和 AMD 自行设计, 制造和销售芯片
  • ARM (RISC 精简指令集)
    • 领地: 智能手机, 嵌入式设备, 物联网. 今年来凭借 Apple M系列芯片进入桌面领域
    • 特点: 设计简洁, 指令定长, 寄存器数量多, 采用 "加载-存储"架构
    • 厂商: ARM公司只设计IP核(架构蓝图), 授权给其他公司(苹果, 高通, 三星, 华为等), 由这些公司自行生产
  • 其他架构
    • MIPS: 经典的RISC设计, 曾在路由器, 嵌入式广泛应用
    • RISC-V: 开源的精简指令集架构, 非常简单化和简洁, 发展迅猛
    • AVR/PIC: 主要用于微控制器(MCU), 是 Arduino 等开发板的核心

主要分支: 语法和工具

确定了架构主干后, 你会遇到具体的 “方言” 和工具

除了不同风格的语法, 不同的汇编器也有会自己的宏和处理指令

  1. x86 分支下两条路
    • Inter 语法
      • 特点: 指令 目标操作数, 源操作数, 例: mov eax, 5
      • 代表汇编器
        • NASM: 跨平台, 开源, 语法清晰一致
        • MASN: 微软官方工具, 主要用于Windows环境
    • AN&T 语法
      • 特点: 指令 源操作数, 目标操作数, 例: mov $5, %eax
      • 代表编译器
        • GAS (GNU Assembler): Linux 和 GCC 编译器的默认后端
  2. ARM 分支下的路
    • 语法: 语法风格相对统一, 主要是 GNU 汇编风格
    • 编译器:
      • GAS: Linux 下编译 ARM 代码的标准工具

共同的地貌: 核心概念

无论你走在哪条主干和分支上, 有些地貌特征是共通的, 这就是汇编语言的 核心概念, 也是学习的重点

  • 寄存器(Registers): CPU 内部高速存储单元
  • 内存寻址模式(Memory Addressing Modes): 如何计算出操作数在内存中的地址. 如 直接寻址, 寄存器间接寻址, 基址变址寻址等.
  • 指令集(Instruction Set)
    • 数据传送: MOV, PUSH, POP, LEA
    • 算数运算: ADD, SUB, INC, DEC, MUL, DIV
    • 逻辑运算: AND, OR, XOR, NOT
    • 控制流: JMP, CALL, RET, 以及各种条件跳转
  • 程序结构(Program Structure): 如何划分代码段, 数据段; 如何使用标签(Labels)
  • 系统调用与中断(Syscalls & Interrupts): 如何让操作系统内核为你服务(例: 输出文字, 读取文件)

延伸: 跨平台 & 跨架构

  • 架构(Architecture): 底层硬件蓝图, 指的是CPU的设计, 它定义了:
    • 指令集: CPU 能够理解和执行的基本命令集合(例: ADD, MOV 等), 不同架构之间最根本的区别
    • 寄存器
    • 内存访问方式
  • 平台(Platform): 完整的运行环境, 指的是硬件架构和操作系统的组合, 它提供了软件运行的完整生态系统
    • Windows on x86-64: 最常见的PC平台
    • Linux on x86-64: 笔记本电脑, 服务器
    • Linux on ARM: 智能手机, 平板, 嵌入式等
    • MaxOS on x86-64: 2019年之前的苹果Mac电脑
    • MaxOS on ARM: 搭载M系列芯片的苹果Mac电脑

跨平台

同一份源代码编译出来的程序, 或者同一个解释型程序, 能够在不同的操作系统上运行, 不需要修改代码

关心的是: 操作系统的差异, 例: 文件路径(c:\ vs /), 动态库格式(.dll vs .so), GUI框架等

如何实现:

  • 用户需要先安装一个 运行时环境 或 虚拟机 (如 JVM, Python解释器), 这个运行时环境本身是需要为特定平台专门编译的
  • 你的源代码被编译成一种中间格式(如java的.class字节码). 这个中间格式是跨平台, 跨架构的. 当用户在具体平台运行它时, 本地的运行环境会负责将中间格式 “翻译” 成当前平台能理解的本地指令

跨架构

同一份源代码编译出来的程序, 能够在不同的CPU架构上运行

关心的是: CPU指令集的差异, 软件必须被编译成目标架构能理解的机器码

如何实现:

  • 方案一: 分发代码

    • 提供程序的源代码, 用户在自己的机器上针对自己的架构自行编译
    • 例: Linux 开源软件
  • 方案二: 提供多个二进制版本

    • 开发者提前为不同的架构分别编译好, 用户根据自己的CPU下载对应的版本
    • 例: Python 官网同时提供 x86-64 和 ARM64 的安装包

总结

以 GAS vs. NASM 为例

特性 GAS (GNU Assembler) NASM (Netwide Assembler)
跨架构 是。一个工具,多种架构 否。只专注于x86/x86-64架构
跨平台 是。可在Win, Linux, macOS等系统上运行 是。可在Win, Linux, macOS等系统上运行
默认语法 AT&T 语法 Intel 语法
“家族” 属于庞大的GNU工具链(GCC, ld, objdump等) 是一个独立的、专注的汇编器

NASM 不支持跨架构 ≠ 无法在ARM架构上的系统安装

让我们分两层理解:

  1. NASM 本身是一个程序, 可以被编译为特定操作系统和架构上运行的版本. 这也是跨平台的特性
  2. NASM 的功能, 无论NASM在哪个操作系统上运行, 它的核心功能只有一个: 将 Inter 语法格式的 x86/x86-64 汇编源代码 汇编成 x86/x86-64 架构的机器码
    因此, 会产生以下情况:
    1. 在 x86 Linux 上: 可以运行 NASM, 它正常工作, 生成 x86 的 .o 目标文件
    2. 在 ARM Linux 上: 你也可以安装和运行一个专门为 ARM 架构编译的 NASM 程序, 但是, 这个 NASM 程序仍然智能处理 x86汇编代码, 并试图输出 x86 机器码.
      • 这在大多数情况下是没有意义的, 生成的x86机器码在 ARM CPU上无法直接执行
      • 这种操作通常只用于 交叉编译的特殊场景, 比如你在一个 ARM 服务器上为 x86 电脑编译程序

网站公告

今日签到

点亮在社区的每一天
去签到