汇编清单里的行并不都是给 CPU 的:有 CPU 指令、有伪指令、有注释、有标签——只有第一类会进内存被执行。
10.2 拿到了汇编清单,这一节讲【怎么读这份清单】。
一、四类行,四个读者
CPU 指令——给 CPU 的:movl、addl、call、ret。 伪指令——给汇编器的:以点开头,比如 .text、.globl、.type、.size。 注释——给人看的:以 // 或 # 开头,谁都不执行。 标签——给汇编器当靶子的:add: 这样的写法,供跳转指令指定目标。 四种行混在一起,不先分辨清楚,读起来就是一团乱麻。
二、伪指令到底在说什么
伪指令有一大类都在交代【这段代码放在哪儿、叫什么、能不能被外面用】。 .text 说:下面是代码段。.globl add 说:add 这个名字允许外部引用。 .type add, @function 说:它是个函数。.size add, .-add 说:它有多长。 这些全是给汇编器和链接器的交代,跟 CPU 一点关系都没有。 所以关键的一句是:汇编器读完伪指令之后,真正的机器码里根本没有它。
三、标签和注释:一个有用,一个没有
标签不是指令,它不占机器码——它只是给一个位置起了名字。 跳转指令写的是名字,汇编器负责把名字换算成地址。 注释在汇编器眼里什么都不算,但它对下一个读代码的人价值最大。 一句话对比:标签是给机器的暗号,注释是给人的便条。
四、数一数就看清了
拿前面那段编译产物的关键行数一下: CPU 指令 6 条,伪指令 5 条,标签 1 个。 也就是说,清单里一半以上的行,CPU 根本看不到。 分辨这一点,是看懂任何汇编清单的第一步。
五、动手 Demo:伪指令与注释
汇编源文件里的行并不都是给 CPU 的。 把上面那段编译产物按类别数一数。
asm_lines = [
("add:", "label"),
("pushl %ebp", "cpu"),
("movl %esp, %ebp", "cpu"),
("movl 8(%ebp), %eax", "cpu"),
("addl 12(%ebp), %eax", "cpu"),
("popl %ebp", "cpu"),
("ret", "cpu"),
]
fakes = [".text", ".globl add", ".type add, @function",
".size add, .-add", ".section .note.GNU-stack"]
cpu = [x for x, k in asm_lines if k == "cpu"]
labels = [x for x, k in asm_lines if k == "label"]
print("CPU 指令", len(cpu), "条")
print("伪指令", len(fakes), "条")
print("标签", len(labels), "个")
实跑输出:
--------------------------------------------------------------------
伪指令与注释
--------------------------------------------------------------------
汇编源文件里的行,**并不都是给 CPU 的。**
类别 谁看 举例
----------------------------------------------------
CPU 指令 CPU movl、addl、call、ret
伪指令 汇编器 .text、.globl、.type、.size
注释 没有人 // 或 # 开头的说明
标签 汇编器 add:、.L2:——给跳转当靶子
**伪指令不是 CPU 指令**,它只是**告诉汇编器【怎么安排、怎么检查】。**
汇编器读完伪指令之后,**真正的机器码里根本没有它。**
拿上面那段编译产物数一数:
CPU 指令 6 条(pushl/movl/movl/addl/popl/ret)
伪指令 5 条(.text、.globl、.type、.size、.section……)
标签 1 个(add:)
**只有 CPU 指令会进内存被执行;其余的,汇编器用完就扔。**
分辨这一点,是看懂任何汇编清单的第一步。
实测:CPU 指令 6 条、伪指令 5 条、标签 1 个。 只有 CPU 指令会进内存被执行;其余的,汇编器用完就扔。
30 秒实验
- 打开一份真实的 .s 文件,把里面的行按四类各标一个颜色。
- 想一想:如果删掉 .globl 那一行,程序还能不能被别的文件引用。
常见误区
- 以为汇编清单里每一行都是指令。伪指令、标签、注释都进不了机器码。
- 以为注释会影响性能。它在汇编阶段就被丢掉了,一个字节都不占。
自测三问(点开对答案)
1. 伪指令是给谁看的? —— 给汇编器的,用来交代代码位置、名字、类型等信息,不会变成机器码。 2. 标签起什么作用? —— 给一个位置起名字,让跳转指令有个可写的目标,汇编器再换算成地址。 3. 为什么说清单里一半以上的行 CPU 看不到? —— 因为伪指令、标签、注释都不进入机器码,只有 CPU 指令会。- ☐ 下一节(10.4 汇编语言的语法是【操作码 操作数】)
相关笔记
- 用C编译器输出汇编语言源代码 — 清单是从哪儿来的
- 汇编语言的语法是【操作码 操作数】 — 剩下那些行怎么读
- 启动代码与库文件 — 链接时还要再补一些东西
- 🔵 计算机基础 · 索引 — 硬件底层的入门课
- ⚙️ 程序是怎样跑起来的 · 索引