|
众所周知,汇编是一门比较古老的语言。国内吶,向来讲究学以致用,当然这不是说这个经世致用的思想不行。按说大学都开这门课的,
但是老师当年自作主张,觉得学这门课在社会上用不到,把汇编语言这门课给换掉了。人家都说老师是引路人,可想而知,
在需要汇编知识的时候方恨读汇编迟。今天所谈,尽量通用且不考虑具体架构,从汇编语言的核心逻辑结构入手。无论是在 x86、ARM
还是 RISC-V 上,汇编语法的本质都是对机器码的文本化描述。
汇编代码的一行通常由四个部分组成:
[标号:] 指令助记符 [操作数] [;注释]
1. 指令助记符 (Mnemonics)
指令是汇编的核心,通常分为以下四大类:
数据传送 (Data Movement)
这类指令负责在寄存器、内存和立即数之间“搬运”数据。
-
MOV / LDR / STR: 将数据从源移动到目的地。
-
PUSH / POP: 栈操作,本质上是修改栈指针(SP)并移动数据。
-
LEA (Load Effective Address): x86 特有,用于计算地址而非读取内容(常被用来做快速加法)。
算术与逻辑运算 (Arithmetic & Logic)
这是 CPU 的 ALU(算术逻辑单元)负责的部分。
流程控制 (Control Flow)
改变程序执行顺序(修改 PC/IP 寄存器)。
2. 操作数 (Operands)
指令操作的对象,通常有三种类型:
-
立即数 (Immediate): 硬编码在指令中的常数。例如 MOV R0, #100 (ARM) 或 mov eax, 100 (x86)。
-
寄存器 (Register): CPU 内部存储单元。如 eax, rbp, r0, x1。
-
内存地址 (Memory): 访问 RAM 中的数据。通常用方括号 [] 表示寻址,例如 [0x401000] 或 [rbp - 8]。
3. 寻址方式 (Addressing Modes)
这是汇编中最灵活也最容易出错的地方。
-
寄存器寻址: MOV EAX, EBX (直接从寄存器读写)。
-
基址变址寻址: [base + index * scale + disp]。
-
例如:MOV EAX, [RBP - 4](访问局部变量)。
-
例如:MOV EAX, [EBX + ESI * 4](访问数组元素)。
-
相对寻址: 跳转指令常用,跳转到当前指令位置的前后偏移量。
4. 标志寄存器与条件执行 (Flags)
每次运算后,CPU 会自动更新一组状态位(EFLAGS / APSR / CSR):
条件执行逻辑:
汇编通过指令后缀或条件跳转利用这些位。例如 JNE (Jump if Not Equal) 实际上检查的是 ZF == 0。
5. 伪指令 (Directives)
这些不是真正的 CPU 指令,而是给汇编器(如 NASM, GAS)看的指令,用于定义数据和段。
6. 两种主流风格对比
在 GDB 中,你可能会看到两种风格:
| 特性 |
Intel 格式 (Windows/NASM) |
AT&T 格式 (Linux/GAS) |
| 顺序 |
指令 目的, 源 |
指令 源, 目的 |
| 寄存器 |
eax |
%eax |
| 立即数 |
10 |
$10 |
| 宽度后缀 |
无 (使用 ptr) |
l (long), w (word) 等 |
| 例子 |
mov eax, 1 |
movl $1, %eax |
总结:
掌握汇编语法的关键在于追踪数据的流动方向以及栈指针(SP)的变化。在 GDB 中,建议始终开启 layout regs,每走一步(si)就盯着寄存器看,这比背诵语法要高效得多。
参考资料:
《简明 X86 汇编语言教程》--司徒彦南 2002 年 4 月 8 日
汇编语言
来源:https://www.cnblogs.com/guxuanqing/p/19875680 |