机器指令到汇编再到高级编程语言( 三 )


机器指令到汇编再到高级编程语言

文章插图
 
例如我们在执行一个叫 main 的函数时,会为它在内存里面创建一个 帧,用来保存所有main 中使用的内部变量 。main 函数执行结束后,该帧就会被回收,释放所有的内部变量,不再占用空间 。
机器指令到汇编再到高级编程语言

文章插图
 
如果在 main 函数 内部调用了其他函数,例如 add_a_and_b 函数,那么执行到这一行的时候,系统也会为 add_a_and_b 新建一个帧,用来储存它的内部变量 。也就是说,此时同时存在两个帧:main 和 add_a_and_b 。一般来说,调用栈有多少层,就有多少帧 。
机器指令到汇编再到高级编程语言

文章插图
 
【机器指令到汇编再到高级编程语言】等到 add_a_and_b 运行结束,它的帧就会被回收,系统会回到函数 main 刚才中断执行的地方,继续往下执行 。通过这种机制,就实现了函数的 层层调用,并且 每一层都能使用自己的本地变量 。
我们可以把栈理解为一个下方密封,而上方打开的「桶」 。
机器指令到汇编再到高级编程语言

文章插图
 
生成的新帧放入我们称之为 「入栈」,而释放帧我们称之为 「出栈」 。栈的特点 就是,最晚入栈的帧最早出栈(因为最内层的函数调用,最先结束运行),这就叫做 "后进先出" 的数据结构 。每一次函数执行结束,就自动释放一个帧,所有函数执行结束,整个栈就都释放了 。
汇编语言演示举个简单的例子,我们需要计算:
(1 + 4) * 2 + 3我们按照 「后缀表示法」 进行一下转换:
1,4,+,2,*,3,+我们平常使用的方法是 「中缀表示法」,也就是把计算符号放中间,例如 1 + 3,后缀则是把符号放最后,例如 1, 3, + 。
这样做的好处是没有先乘除后加减的影响,也没有括号,直接运算就行了 。(例如 1, 3, +,先把 1 和 3 保存起来碰到 + 知道是加法则直接相加)
OK,我们从头开始使用汇编语言来编写一下程序,首先第一步:把 1 保存起来(放入寄存器):
MOV1之后是 4, +,那就直接加一下:
ADD 4然后是 2, *,那就直接乘一下(SHL 是向左移动一位的意思,二进制中左移一个单位就相当于乘以 2,例如 01 表示 1,而 10 则表示 2):
SHL 0最后是 3, +,再加一下:
ADD 3完整程序如下:
MOV1ADD4SHL0ADD3这似乎看起来比 00001111 这样的二进制要好上太多了!程序员们感动到落泪:
机器指令到汇编再到高级编程语言

文章插图
 
Part 3. 高级编程语言
机器指令到汇编再到高级编程语言

文章插图
 
摆脱了 二进制,我们有了更可读的 汇编语言,但仍然十分繁琐和复杂,每一条汇编指令代表一个基本操作,例如:「从内存 x 位置获取一个数字并放入寄存器 A」、「将寄存器 A 中的数字添加到寄存器 B 的数字上」 。这样的编程风格既费时又容易出错,并且一旦出错还很难发现 。
例如,我们来看一看 「1969 年阿波罗 11号登月计划」 用来 防止登月舱计算机耗尽自身资源 的 BAILOUT 代码:
POODOOINHINTCAQTSALMCADRTCBANKCALLCADRVAC5STOR# STORE ERASABLES FOR DEBUGGING PURPOSES.INDEXALMCADRCAF0ABORT2TCBORTENT OCT77770OCT77770# DONT MOVECAV37FLBIT# IS AVERAGE G ONMASKFLAGWRD7CCSATCWHIMPER -1# YES.DONT DO POODOO.DO BAILOUT.TCDOWNFLAGADRESSTATEFLGTCDOWNFLAGADRESREINTFLGTCDOWNFLAGADRESNODOFLAGTCBANKCALLCADRMR.KLEANTCWHIMPER
  • 出处:改变世界的代码行 - https://www.infoq.cn/article/5CaYH8NbS6BmptWKRgkX
似乎不太容易读的样子...

阿波罗登月计划的源代码在 Github 上已经公开,有兴趣的可以去下方链接膜拜一下(可以去感受一下当时程序员的工程能力):
https://github.com/chrislgarry/Apollo-11
另外附一下当时代码的设计负责人 Margaret Heafield Hamilton(女程序员)和完成的堆起来跟人一样高的代码量:
第一个高级语言:FORTRAN当 John Backus 在 1950 年以一名科学程序员的身份加入 IBM 时,已经可以使用诸如 ADD 之类的助记词代替数字代码来编写程序,也就是我们的汇编语言 。这使编程变得容易一些,但是即使是一个简单的程序也需要数十次操作,并且仍然很难找到错误 。


推荐阅读