资料来源:汇编语言第二版-王爽
1.源程序例子:
assume cs:codesg
codesg segment
start : mov ax, 0123H
mov bx, 0456H
add ax, bx
add ax, ax
mov ax, 4C00H
int 21H
codesg ends
end start
在汇编语言源程序中,包含两种指令,一种是汇编指令,一种是伪指令。
2.汇编指令
汇编指令是有对应的机器码的指令,可以被编译为机器指令,最终为CPU所执行。
例如:mov、add、sub等指令
3.伪指令
伪指令没有对应的机器码,不被CPU所执行,它是由编译器来执行的指令,编译器根据伪指令来进行相关的编译工作。
上面的例子中出现了三种伪指令:
(3.1)segment指令和ends指令
segment和ends是一对成对使用的伪指令,这是在写可被编译器编译的汇编程序时,必须使用到的一对伪指令。
segment和ends的功能是定义一个段,segment说明一个段开始,ends说明一个段结束。一个段必须有一个名称来标识,使用格式为:
段名 segment
:
:
:
段名 ends
比如上述例子中的:
codesg segment ;定义一个段,段的名称为"codesg",这个段从此开始。
:
codesg ends ;名称为"codesg"的段到此结束
一个汇编程序是由多个段组成的,这些段被用来存放代码、数据或者当作栈空间来使用。
前面学习的段的概念,在汇编源程序中得到了应用与体现,一个源程序中所有将被计算机所处理的信息:指令、数据、栈,被划分到了不同的段中。
一个有意义的汇编程序中至少要有一个段,这个段用来存放代码。
从上述例子中我们可以看到,在codesg segment和codesg ends之间写的汇编指令是这个段中存放的内容,这是一个代码段。
(3.2)end 指令
end是一个汇编程序的结束标记,编译器在编译汇编源程序的过程中,如果碰到了伪指令end,就结束对源程序的编译。所以,在我们写程序的时候,如果程序写完了,要在结尾处加上伪指令end。否则,编译器在编译源程序时,无法知道程序在何处结束。
注意,还要搞混了end和ends,ends是和segment成对使用的,标记一个段的结束,ends的含义可以理解为"end segment"。
我们在这里讲的end的作用是标记整个程序的结束。
(3.3)assume 指令
这条伪指令的含义是"假设",它假设某一段寄存器和程序中的某一个用"segment ··· ends"定义的段相关联。
通过assume说明这种关联,在需要的情况下,编译程序可以将段寄存器和某一个具体的段相关联。
assume并不是一条非要深入理解不可的伪指令,我们编程时记着用assume将有特定用途的段和相关的寄存器关联起来即可。
比如,在上述例子中,我们用codesg segment ··· codesg ends定义了一个名为codesg的段,在这个段中我们存放代码,所以这个段是一个代码段。我们在程序的开头,用assume cs:codesg将用作代码段的段codesg和CPU中的段寄存器cs联系起来。
4.源程序中的"程序"
我们可以将源程序文件中的所有内容称为源程序,将源程序中最终由计算机执行、处理的指令或数据,称为程序。程序最先以汇编指令的形式存在源程序中,经编译、连接后转变为机器码,存储在可执行文件中。
5.标号
汇编源程序中,除了汇编指令和伪指令外,还有一些标号,比如"codesg"。一个标号指代了一个地址。比如codesg在segment前面,作为一个段的名称,这个段的名称最终将被编译、连接程序处理为一个段地址。
6.程序的结构
汇编源程序是由一些段构成的。我们可以在这些段中存放代码、数据或者将某个段当作栈空间来使用。
例如:
assume cs:code, ds:data, ss:stack
;定义"code"标号与代码段寄存器cs相关联
;定义"data"标号与数据段寄存器ds相关联
;定义"stack"标号与栈段寄存器ss相关联
data segment
dw 0123H, 0456H, 0789H, 0abcH, 0defH, 0fedH, 0cbaH, 0987H
;在数据段中定义相关数据
data ends
stack segment
dw 0, 0, 0, 0, 0, 0, 0, 0
;在栈段中定义栈段空间大小
stack ends
code segment
;在代码段中编写汇编指令完成程序运行逻辑
start: mov ax, stack
mov ss, ax ;设置栈段寄存器ss指向stack段
mov sp, 16 ;设置栈顶指针ss:sp指向stack:16位置
mov ax, data
mov ds, ax ;设置数据段寄存器ds指向data段
mov bx, 0 ;设置ds:bx指向data段中的第一个单元
push ds:[bx] ;将ds:[bx]中的内容入栈
pop ds:[bx] ;从栈中取出数据送入ds:[bx]指向的内存单元
mov ax, 4C00H
int 21H
code ends
end start
;在程序末尾添加end指令结束程序编译
上述例子中分别定义了数据段、栈段和代码段的标号,并且与相应的段寄存器相关联,然后在程序开始后,先设置了栈段寄存器ss、栈顶指针sp和数据段寄存器ds,最后在程序结尾处添加了end指令。
这只是一个非常简陋的例子,没有任何功能,只是演示了一个汇编源程序的布局结构而已。
有错误请指正,谢谢!