汇编的编程过程
以下是一个汇编程序从写出到最终执行的简要过程:
- 使用文本编辑器编写汇编源程序,得到一个
.asm
的文件 - 对源程序进行编译(compile),得到
.obj
目标文件 - 对目标文件进行链接(link),得到
.exe
可执行文件 - 执行可执行文件,运行程序
链接的作用有:
- 当程序很大时,需要拆分为多个源文件进行编译,最终只需要将编译结果链接在一起便可得到可执行文件,便于分块管理
- 当程序调用了某个库文件中的子程序时,需要将这个库文件和生成的目标文件链接到一起,生成一个可执行文件
- 源程序编译后得到的内容有时还不能直接用来生成可执行文件,需要进一步处理
第一个源程序及其结构
以下是一段简单的汇编语言源程序:
下面是源程序的一些要点:
伪指令
汇编语言源程序中,包含了两种指令:汇编指令和伪指令。
汇编指令是有对应的机器码的指令,可以被编译为机器指令,由CPU执行。
伪指令没有对应的机器指令,仅由编译器执行,编译器通过伪指令完成相关的编译工作。以上程序出现了三种伪指令:
...
segname ends
segment 和 ends 是一对成对使用的伪指令,这是在编写可被编译器编译的汇编程序时必要的一对伪指令。
这一对伪指令的作用是定义一个段,segment 说明一个段的开始,ends 说明一个段的结束。一个段必须要使用一个名称 segname 来作为标号进行标识,并且一对 segment 和 ends 的标号必须要相同。
一个汇编程序是由多个段构成的,因为程序中所有被计算机所处理的信息:指令、数据、栈,都被划分到了不同的段中。一个有意义的汇编程序中至少要有一个段,这个段用来存放代码。
end 是一个汇编程序的结束标记,编译器在编译汇编时,以 end 作为结束编译的标志。
不要混淆了 end 和 ends 。ends 可以理解为end segment。
assume 伪指令的意思是假设某一段寄存器和程序中的某一个用 segment...ends 定义的段相关联,通过 assume 说明这种关联。
例如,在本程序的开头,使用 assume cs: codesg
将用作代码段的段 codesg
和段寄存器 CS 联系在一起。
具体的内容无需深入了解。
程序返回
一个程序结束后,应该将CPU的控制权还给运行它的程序。
以上示例程序,让程序返回的指令为:
目前不必理解它的含义以及为什么能让程序返回,只需要知道这样做能让程序返回即可。
下表列出了一些与结束相关的概念:
目的 | 相关指令 | 指令性质 | 指令执行者 |
---|---|---|---|
标志段的结束 | segname ends | 伪指令 | 编译期间,编译器执行 |
标志程序的结束 | end | 伪指令 | 编译期间,编译器执行 |
程序返回 | MOV AX, 4C00H INT 21H |
汇编指令 | 执行期间,CPU执行 |
一些约定的记号
为了方便表述,以下约定一些具有特殊含义的记号:
- 使用描述性符号“
()
”来表示表示一个寄存器或一个内存单元中的内容
例如,“ (AX)
”表示寄存器 AX 中的值,“ (BX)
”表示寄存器BH中的值,“ (20000H)
”表示物理地址为20000H的存储单元中的值,“ ((DS):(BX))
”表示段地址为 DS 中的值,偏移地址为 BX 中的值所指向的物理地址代表的存储单元中的值。
该值对应的可能是字节型数据,也可能是字型数据,具体取决于具体的运算。
- 使用关键字 n 表示一个合适的任意常量(字面量)
例如,“ MOX AX, [n]
”就表示移动一个合适的内存空间的值到寄存器 AX 上,它可以代表 [0]
、[1]
、[2]
等任意值,是一个泛指。