终于聊完了 CPU 的寄存器部分,不禁长舒一口气,今天我们来到程序的部分。
程序,相信大家在学完 C 和 C++后应该不陌生了。(不会有人将汇编作为第一们语言学吧?)如此,程序如何从源文件(source)变成可执行文件(.exe),这里不再赘述。
我们直接来看一段完整的汇编语言源程序:
assume cs:codesg
codesg segment
mov ax,0123H
mov bx,0456H
add ax,bx
add ax,ax
mov ax,4c00H
int 21H
codesg ends
end
程序语言分类
我们通过这段程序填下第一篇汇编语言炉边小坐的坑:
1、伪指令
在汇编语言源程序中,包含两种指令,一种是汇编指令,一种是伪指令。汇编指令是有对应的机器码的指令,可以被编译为机器指令,最终为CPU所执行。而伪指令没有对应的机器指令,最终不被CPU所执行。那么谁来执行伪指令呢?它是由编译器来执行的,编译器根据伪指令来进行相关的编译工作。举个不太相关的例子,对于一个高达模型而言,汇编指令就像是构成高达的一块块部件(胶),而伪指令就像是工人雕刻模具的工艺、方法等等,伪指令告诉工人如何雕刻模板(执行指令),而高达就是指令执行的产物,高达模型本身不体现对工人的工艺指导等等细节(最终不被CPU所执行。),它只体现指令执行的结果(汇编指令最终为CPU所执行)。表述的有点踉跄,希望不是胶佬的你也能理解。
(1)在上面,segment 和 ends 是一对伪指令,他们搭配使用,表示一个段的开始与结束。而 codesg 是这个代码段的名字。
一个汇编程序是由多个段组成的,这些段被用来存放代码、数据或当作栈空间来使 用。我们在前面的课程中所讲解的段的概念,在汇编源程序中得到了应用与体现,一个源 程序中所有将被计算机所处理的信息:指令、数据、栈,被划分到了不同的段中。
一个有意义的汇编程序中至少要有一个段,这个段用来存放代码。
我们可以看到,程序中,在codesg segment和codesg ends之间写的汇编指令是这 个段中存放的内容,这是一个代码段 ——《汇编语言(第三版)》王爽
(2)end
end 伪指令是程序结束的标志。不要搞混淆 end 和 ends。
(3)assume
这条伪指令的含义为“假设”。它假设某一段寄存器和程序中的某一个用 segment...ends定义的段相关联。通过assume说明这种关联,在需要的情况下,编译程 序可以将段寄存器和某一个具体的段相联系。assume并不是一条非要深入理解不可的伪指令,以后我们编程时,记着用assume将有特定用途的段和相关的段寄存器关联起来即可。
比如,在程序4.1中,我们用codesg segment ... codesg ends定义了一个名为codseg 的段,在这个段中存放代码,所以这个段是一个代码段。在程序的开头,用assume csxodesg将用作代码段的段codesg和CPU中的段寄存器cs联系起来。
值得指出的是,汇编语言从源文件到可执行文件稍有不同。
下面来浅析汇编语言程序结构:
比如,我们要写一个程序,运算 2^3,我们如何写?
1、定义一个段,名称随意
wtf segment
:
:
wtf ends
2、在这个段内写入汇编指令
wtf segment
mov ax,2
add ax,ax
add ax,ax
wtf ends
3、指出程序的结束位置
wtf segment
mov ax,2
add ax,ax
add ax,ax
wtf ends
end
4、既然 wtf 要被当成代码使用,那就应该将 wtf 和 cs 联系在一起(cs 指明要运行的程序在何处储存,详情翻见:2021-7-22~23 汇编语言 寄存器-CPU 的办事大厅【完成版】(炉边小坐)以及2021-7-24~25 汇编语言 寄存器(内存访问)-办事大厅指南【完成版】(炉边小坐))
assume cs:wtf
wtf segment
mov ax,2
add ax,ax
add ax,ax
wtf ends
end
这样一个程序就写好了。
关于程序运行
程序返回
我们的程序最先以汇编指令的形式存在源程序中,经编译、连接后转变为机器码,存储在可执行文件中,那么,它怎样得到运行呢?
我基于DOS(一个单任务操作系统)的基础上讨论这个问题。
一个程序P2在可执行文件中,则必须有一个正在运行的程序P1,将P2从可执行文件中加载入内存后,将CPU的控制权交给P2, P2才能得以运行。P2开始运行后,P1暂停运行。而当P2运行完毕后,应该将CPU的控制权交还给使它得以运行的程序P1,此后,P1继续运行。
现在,我们知道,一个程序结束后,将CPU的控制权交还给使它得以运行的程序, 我们称这个过程为:程序返回。那么,如何返回呢?应该在程序的末尾添加返回的程序段。
assume cs:codesg
codesg segment
mov ax,0123H
mov bx,0456H
add ax,bx
add ax,ax
mov ax,4c00H
int 21H
codesg ends
end
其中, mov ax,4c00H,int 21H就是用于实现程序返回的功能。现阶段,我们只需要记忆,就像模板一样打上去就 OK。
注:关于程序编程、编译、连接、跟踪先按下不表。