名字、标签与地址
复习
- 中断系统:外设可主动通知 CPU,CPU 保存现场后处理再恢复
- 第一次呼吸:把 CPU、存储器、总线和外设合起来,让完整计算机自动运行
- 用汇编语言指挥计算机:用助记符代替难读的二进制机器指令
TL;DR
- 手工数地址既费神又易错,于是给数据和位置起个名字
- 标签 是地址的别名,写起来是人话,落到机器还是地址
- 名字让代码更好读、更好改;插入或删除一行,不必重算其它地址
- 机器只认地址,所以需要一个程序把名字翻译回地址
正文
上一章结尾留了个问题:程序里的 20、21、22,全是我们一个个数出来的。数一两个还行,可程序一大,这就成了噩梦。
举个例子。假设我们在前面插入了一条新指令,后面所有指令的地址都会往后挪一格。凡是引用了旧地址的地方,都得挨个改。漏掉一个,程序就跑飞了。
人解决重复劳动的老办法,还是 起名字 。
给数据起名字
把“地址 20 里放着 3”这件事,改说成“有一个叫 x 的数据,值是 3”:
LOAD A, [x]
LOAD B, [y]
ADD R, A, B
STORE [sum], R
HALT
x: .data 3
y: .data 5
sum: .data 0
x:、y:、sum: 后面跟着 .data,意思是“这里放一个数据,给它起这个名字”。从这一刻起,我们再也不用记“3 在地址 20”——只要说 [x] 就行。
给位置起名字
不只是数据,跳转的目标也能起名字。上一章说过 JMP 和 JZ 会改 PC,可“改到哪”总得有个地址。于是这样写:
start: LOAD A, [x]
LOAD B, [y]
ADD R, A, B
STORE [sum], R
JZ done
JMP start
done: HALT
start: 和 done: 就是两个 标签 (label)。JMP start 读作“跳回 start 那里”。至于什么时候跳、跳几次,那是分支和循环要讲的事,这里先看个大概就好。
标签到底是什么
标签不是新硬件,也不是什么魔法。它只是 地址的别名 。上面那几行,等价于:
| 名字 | 真正的地址 |
|---|---|
start | 0 |
x | 5 |
y | 6 |
sum | 7 |
done | 5 |
(这里只是示意,真实地址取决于每条指令占几个存储单元。)
所以,写程序时可以满口 x、sum、start,等程序真正运行,PC 里跑的、地址线里传的,仍然是冷冰冰的数字。名字是给人看的,地址才是给机器用的。
名字的价值
有了名字,好处立刻显现:
- 可读 :
STORE [sum], R比0100 00010110一眼就懂 - 好改 :在
start前面插一条指令,后面的标签会自动跟着挪,引用它们的地方一个字都不用动 - 少错 :再也不用担心把
21手滑写成12
名字把“人关心的意义”和“机器关心的位置”分开了。这又是一层抽象。
谁来翻译这些名字
可是机器不认识 x,也不认识 start。总得有人把“名字”换算成“地址”,把写在纸上的汇编变成能塞进存储器的 0 和 1。
这个干活的程序,正是下一章的主角—— 汇编器 。
思考题
同一段程序,把
x改成a、sum改成total,机器码会不会变?为什么?
小结
知识点
- 用名字代替手工地址
- 标签:地址的别名,用于数据和跳转目标
- 名字让人好读好改,机器最终仍然使用地址
- 名字与地址的换算需要汇编器完成
参考资料
- Wikipedia(zh):汇编语言:标签与符号
- Wikipedia(zh):符号表:名字与地址的对照
思考题答案(仅供参考)
不会。名字只是给地址起的别名,改成 a、total 之后,地址并没有变,汇编器把它们翻译出来的机器码自然完全一样。这也说明:名字是给人看的,机器看到的始终只是地址和比特。
协议
本作品采用知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议进行许可。
封面图
设计师 | 南国微雪