教学重点本章重点掌握:
程序的格式,开发方法
参数的表达,变量的定义
变量和标号的属性第一章 基础知识第五章 汇编语言程序结构第一章 基础知识机器语言 —计算机能够直接识别并执行的二进制机器指令序列优点,开销小、运行速度快 ;
缺点:难以编写和理解,编程效率很低。
汇编语言 ( Assembly Language) —用助记符号表示机器指令代码、变量地址,标号等的符号指令序列。
优点,易记、易理解,易编写程序,大大提高了编程效率 ;
问题:需要将助记符号翻译为机器语言。
汇编语言源程序,用汇编语言 编写的程序 。
汇编程序,将助记符号翻译为机器语言的 语言处理程序,以便计算机能够识别。
汇编,将助记符号 翻译 为机器语言的 过程 。
理解以上几个名词概念:
汇编语言、汇编语言源程序、汇编程序、汇编概 念第一节:汇编程序功能及上机过程汇编程序功能汇编程序的 主要功能 如下:
( 1) 检测语法错 显示错误信息
( 2) 源程序文件 二进制目标文件 ( 并输出 *.LST文件 )
( 3) 展开宏指令一般汇编程序都应具有如下功能,
宏汇编功能
支持地址和数据的符号表示
支持内存管理
支持程序的模块化组织
支持多种类型的数据表示等汇编程序 依赖于硬件,不同机型的系统有自己的汇编程序。
上机过程上机过程如图所示第一章 基础知识第五章 汇编语言程序结构汇编语言源程序的结构与书写格式汇编语言源程序是段结构的:
代码段、数据段、堆栈段、
附加段源程序 由段组成,每段有一个 段名,segment
定义段起点,
ends定义段结束点。每段由若干语句行 组成,源程序以 end结束。
例 字符串传送指令和伪指令
指令 ——使 CPU产生动作、并在程序执行时才处理的语句,就是前一章学习的处理器指令
伪指令 ( Directive) ——不产生 CPU动作、在程序执行前由汇编程序处理的说明性语句,例如,数据说明、变量定义等等
伪指令与具体的处理器类型无关,但与汇编程序的版本有关本课程采用微软宏汇编程序 MASM 5.0
汇编语言语句一般格式为:
[标识符 /语句标号 ] 指令名 [操作数序列 ] [;注释 ]
标识符 ——用来为变量,段及过程等命名语句标号 ——标识符后加?,?,提供转移地址指令名 ——指令可分为三类:机器指令,伪指令和宏指令 。
机器指令,指令系统中的指令,程序运行时 由 CPU执行 ;
伪指令,汇编程序执行 的操作,规定汇编程序如何按要求进行汇编及分配内存 。
宏指令,由一系列指令或伪指令构成,汇编时展开 成若干条机器指令,用于提高编程效率 。
操作数序列 ——可以是常量,变量,表达式,寄存器名或标号等,用逗号隔开 。
( 伪指令和宏指令由汇编程序在汇编期间处理 )
注释符 ——,;,后可给出语句注释,提高可读性和可理解性 。
第二节:汇编语言语句格式与分类
( 1)常量
00110110B 389D 467O B407H
3.475E+5 'Input a number'
( 2)变量变量名:存储单元的符号地址变量值:存储单元中的数据
MOV AL,'A'
mov al,'a'
变量的三种属性:
段值( SEG):变量所在 段的起始地址偏移量( OFFSET):段起点距离变量所在存储单元位置的 字节数
50
偏移量段起点
类型( TYPE):变量 占用的字节数常量、变量、标号
( 3)标号标号,存放指令的存储单元的 符号地址,常用作转移地址。
NEAR,2字节转移地址

CMP AX,BX
JNE NEXT

NEXT,MOV AX,0

标号的三种属性:
段值( SEG):标号所在段的起始地址偏移量( OFFSET):段起点距离标号所指存储单元位置的字节数类型( TYPE),NEAR,FAR
(偏移地址) 短指针 (近指针 ) 段内转移
FAR,4字节转移地址 (段、偏移地址) 长指针 (远指针 ) 段间转移第一章 基础知识第五章 汇编语言程序结构汇编语言程序的语句类型:
1、程序执行指令语句。
2、伪操作语句。
3、宏指令语句。
伪操作的功能,伪操作又称为伪指令,它不象机器指令那样是在程序运行期间由计算机来执行的,它是在汇编程序对源程序汇编期间由汇编程序处理的操作,它们可以完成如下功能:
( 1)符号定义伪指令 ( 2)数据定义伪指令
( 3)段定义伪指令 ( 4) 过程定义伪指令
( 5)条件汇编伪指令 ( 6)宏指令
( 7)结构与记录一,数据定义及存储器分配伪操作格式:
[Variable] Mnemonic Operand,…,Operand [;Comments]
变量 ( Variable) 字段,是可有可无的,它用符号地址表示,其作用与指令语句前的标号相同,但它的后面不跟冒号 。 如果语句中有变量则汇编程序使其记以第一个字节的偏移地址 。
第一章 基础知识第五章 汇编语言程序结构注释 (Comments)字段,用来 说明 该伪操作的功能,它也是可有可无的 。
助记符 (Mnemonic)字段,说明所用伪操作的助记符,常用的有以下几种:
DB伪操作,用来定义字节,其后的每个操作数都占有一个字节 。
DW的操作,用来定义字,其后的每个操作数占有一个 字 (低位字节在第一个字节地址中,高位字节在第二个字节地址中 )。
DD伪操作,用来定义双字,其后的每个操作数占有二个字 。
DQ伪操作,用来定义四个字,其后的每个操作数占有四个字 。
DT伪操作,用来定义十个字节,其后的每个操作数占有十个字节
,形成压缩的 BCD码 。
这些伪操作可以把其后面跟着的数据存入指定的存储单元,或者只分配存储器空间而并不存入确定的数值。 DW和 DD伪操作可以存储偏移地址或完整的地址 。
第一章 基础知识第五章 汇编语言程序结构例 操作数可以是常数,或者是表达式 (根据该表达式可以求得一个常数 ),如
DATA_BYTE DB 10,4,l0H
DATA_WORD DW 100,100H,-5
DATA—DW DD 3*20,0FFFDH
汇编程序可以在汇编期间在存储器中存入数据,如右图所示。
例 操作数也可以是字符串,如:
MESSAGE DB ‘H2LLO’
则存储器存储情况如下图所示:
第一章 基础知识第五章 汇编语言程序结构注意,DB ’AB’和 DW ’AB’ 的存储 分配空间的不同。如下图:
例 操作数? 可以保留存储空间,但不存入数据 。
如,ABC DB 0,?,?,?,0
DFF DW?,52,?
经汇编后的存储情况如右图所示。
第一章 基础知识第五章 汇编语言程序结构操作数字段还可以使用复制操作符来复制某个 ( 或某些 ) 操作数 。 其格式为,
repeat_count DUP(operate,operate,…)
其中 repeat_count可以是一个表达式,
它的值应该是一个正整数,用来指定括号中的操作数的重复次数。
例 ARRAYl DB 2 DUP(0,1,2,? )
ARRAY2 DB 100 DUP(? )
汇编后的存储情况如下图所示。
ARRAYl DB 2 DUP(0,1,2,? )
和以下语句是等价的:
ARRAYl DB 0,I,2,?,0,1,2,?
第一章 基础知识第五章 汇编语言程序结构例 DUP操作可以嵌套,例如
ARRAY3 DB 100DUP(0,2 DUP(1,2),0,3)
则汇编结果如右图所示:
可以用 DW或 DD伪操作把变量或标号的偏移地址
(DW)或整个地址 (DD)存入存储器。用 DD伪操作存入地址时,第一个字为偏移地址,第二个字为段地址。
例如
PARAMETER_TABLE DW PAR1
DW PAR2
DW PAR3
INTERSEG_DATA DD DATA1
DD DATA2
则汇编后的存储情况如下图所示。其中偏移地址或段地址均占有一个宇,其低位字节占有第一个字节,高位字节占有第二个字节。
第一章 基础知识第五章 汇编语言程序结构第一章 基础知识第五章 汇编语言程序结构顺便说明一下,这里操作数字段中的变量或标号可以使用表达式如,
在这种情况下,汇编后,存储器中应该存入表达式的值 。
例如
PARAMETER_TABLE DW PAR1+1
DW PAR2+1
说明变量的类型属性问题,
在数据定义伪操作前面的变量的值是该伪操作中的第一个数据项在当前段内的第一个字节的偏移地址 。 此外,它还有一个类型属性用来表示该语句中的每一个数据项的长度 (以字节为单位表示 ),因此 DB伪操作的类型属性为 1,
DW为 2,DD为 4,DQ为 8,DT则为 10,变量表达式的属性和变量是相同的 。
汇编程序可以用这种隐含的类型属性来确定某些指令是字指令还是字节指令。
第一章 基础知识第五章 汇编语言程序结构例如 OPER1 DB?,?
OPER2 DW?,?

MOV OPER1,0
MOV OPER2,0
则第一条指令应为字节指令,第二条指令则应为字指令。
如果有下列指令序列,
OPER1 DB 1,2
OPER2 DW 1234H,2345H

MOV AX,OPER1+1
MOV AL,OPER2
汇编程序在汇编这一段程序时,能发现两条 MOV指令的两个操作数的类型属性是不相同的:
OPERl十 1为字节类型属性而 AX为字类型属性;
OPER2为字类型属性而 AL为字节类型属性。
汇编语言将指示由于属性类型不匹配出错。
第一章 基础知识第五章 汇编语言程序结构有一个办法可以指定操作数的类型属性,
它优先于隐含的类型属性,即可以使用
PTR属性操作符 。 其格式为:
type PTR Varible士 constant expression
其 中 类 型 可 以 是 BYTE,WORD 或
DWORD(双字 ),这样变量的类型就可以指定了 。 上面例子可以写为:
OPER1 DB 1,2
OPER2 DW 1234H,2345H

MOV AX,WORD PTR OPER1+1
MOV AL,BYTE PTR OPER2
通过 PTR属性操作符就把 OPER1十 1
的类型属性指定为字,两个操作数的属性就一致了,汇编时不会出错,
而运行时应把 OPER1十 1的字内容送到 AX,即把 OPER1十 1的内容送 AL,
把 OPER2的第一个字节的内容运 AH,
所以指令执行完后,(AX)= 3402H。
同样,对于第二条语句( AL) =34H
第一章 基础知识第五章 汇编语言程序结构
LABEL伪操作,
除了用属性操作符给以定义外,还可以用 LABEL伪操作来定义,其格式为:
name LABEL type
( 1) 对于数据项可以表示为:
variable_name LABEL type
其中,type可以是 BYTE,WORD或 DWORD(双字 )。
( 2) 对于可执行的代码,则可表示为
label_name LABEL type
其中,type可以是 NEAR或 FAR。
第一章 基础知识第五章 汇编语言程序结构例如 4.9
BYTE_ARRAY LABEL BYTE
WORD_ARRAY DW 50 DUP(?)
这样在 100个字节数组中的第一个字节的地址赋于二个不同类型的变量名:
字节类型的变量 BYTE_ARRAY和字类型变量 WORD_ARRAY。
指令
MOV WORD_ARRAY十 2.,0
把该数组的第 3个和第 4个字节置 0,而
MOV BYTE_ARRAY十 2.,0
则把该数组的第 3个字节置 0。
例,LABF LABEL FAR
LAB,MOV AX,100
第一章 基础知识第五章 汇编语言程序结构二、表达式赋值伪操作 EQU
有时程序中多次出现同一个表达式.为方便起见可以用赋值伪操作给表达式赋予一个名字,其格式如下:
此后,程序中凡需要用到该表达式之处就可以用表达式名来代替了。
上式中的表达式 可以是任何有效的操作数格式,可以是任何可以求出常数值的表达式,也可以是任何有效的助记符。 举例如下:
第一章 基础知识第五章 汇编语言程序结构必须注意 EQU语句的表达式中如果有变量或标号的表达式,则在该语句前应该先给出它们的定义。 例如,语句,
则必须放在 DATA_ONE的定义之后才行,否则汇编程序将指示出错。
另外还有一个与 EQU相类似的 = 伪操作也可以作为赋值伪操作使用 。 它们之间的区别是,EQU伪操作中的表达式名是不允许重复定义的,而 = 伪操作则允许重复定义 。
例如,EMP = 6 或 EMP EQU 6都可以使数 6赋以符号名 EMP,但是不允许两者同时使用。
第一个语句后的指令中 EMP值为 7;而第二个语句后的指令中 EMP值为 8。
第一章 基础知识第五章 汇编语言程序结构三、段定义伪操作存储器的物理地址是由段地址和偏移地址组合而成的,汇编程序在把源程序转换为目标程序时,必须确定标号和变量的偏移地址,并且需要把有关信息通过目标模块传送给连接程 序,以便连接程序把不同的段和模块连接在一起形成一个可执行程序 。 为此,需要用段定义伪操作,段定义伪操作的格式如下,
此外,还要明确段和段寄存器的关系,这可用 ASSUME伪操作来实现,其格式为:
其中 assignment说明分配情况,其格式为:
其中段寄存器名必须是 CS,DS,ES和 SS中的一个,而段名则必须是由
segment定义的段中的段名。
而 ASSUME NOTHING则可取消前面由 ASSUME所指定的段寄存器。
第一章 基础知识第五章 汇编语言程序结构例如:
由于 assume伪操作只是指定某个段分配给那一个段寄存器,它并不能把段地址装入段寄存器中,所以在代码段中 。 还必须把段地址装入相应的段寄存器中 。
为此,在上例的程序中,分别用两条 MOV指令完成这一操作 。 如果程序中有堆栈段,也需要把段地址装入 SS中 。 但是,代码段不需要这样做,代码段的这一操作在程序初始化时完成 。 功能:
通知 MASM用指定的段寄存器来寻址对应的逻辑段,即建立段寄存器与段的缺省关系
在明确了程序中各段与段寄存器之间的关系后,汇编程序会根据数据所在的逻辑段,在需要时自动插入段超越前缀。
这是 ASSUME伪指令的主要功能
ASSUME伪指令并不为段寄存器设定初值,连接程序 LINK
将正确设置 CS,IP和 SS,SP
由于数据段通常都需要,所以在样板源程序中,首先为 DS
赋值;如果使用附加段,还要赋值 ES
段寄存器的装入
DS和 ES的装入通过寄存器传送如,MOV AX,DATA1
MOV DS,AX
MOV AX,DATA2
MOV ES,AX
SS的装入
( 1)自动装入采用定义段时指定组合类型 STACK参数,在 ASSUME语句中建立 SS的关系,这样就可以自动装入 SS。
SS段寄存器的装入
stack1 segment para stack
dw 40h dup(?)
stack1 ends
……
code1 segment
assume cs:code1,ss:stack1,……
……
SS段寄存器的装入
(2) 程序设置
stack1 segment para stack
dw 40h dup(?)
top label word
stack1 ends
……
code1 segment
assume cs:code1,ss:stack1,……
……
mov ax,stack1
mov ss,ax
mov sp,offset top
……
CS和 IP的装入
(1)初始化时装入,根据 END伪指令指示的地址
END [标号 ]
END语句的作用:
告诉汇编程序,源程序结束指定程序运行时的起始地址,即:
seg 标号 cs
offset 标号 ip
汇编结束伪指令END [标号 ]
指示汇编程序 MASM到此结束汇编过程
源程序的最后必须有一条 END语句
可选的标号用于指定程序开始执行点,连接程序将据此设置 CS,IP值
————不要糊涂 ————
程序终止和汇编结束是两码事
CS和 IP的装入
(2)自动修改 CS和 IP
执行 CALL FAR和 RET指令执行 JMP FAR指令响应中断及中断返回( IRET)
RESET
……
第一章 基础知识第五章 汇编语言程序结构
SEGMENT伪操作还可以增加类型及属性的说明,格式如下,
一般情况下,这些说明可以不用。但是,如果需要用连接程序把本程序与其他程序模块相连接时,就需要使用这些说明。分别叙述如下:
* 定位类型 (align_type)可以是,
段名 SEGMENT [定位类型 ] [组合类型 ] [段字 ][类别名 ]
段名 ENDS
实际上定位类型可以理解为 "对两个相临段的段地址给予的一些规定 "。定位类型可以有以下几种:
PARA:指定所定义的段开始于小段边界,实际是规定这个段的起始地址与前面一个段的起始地址之差必须是 16字节的整数倍。这意味着相临两个段的段地址之差最小也得是 1。
PAGE:指定定义的段开始于页边界,实际是规定这个段的起始地址与前面一个段的起始地址之差必须是 256字节的整数倍。
BYTE:所定义的段开始于字节边界,实际上是指这个段可以从任何地址开始。
WORD:所定义的段开始于字边界,实际是指这个段只能从偶数地址开始。
如果源程序中指定了段的定位类型为 PARA或 PAGE,那么获得的可执行文件中相临段的段地址就有差异。
但是如果源程序中指定了段的定位类型是 BYTE或 WORD,那么在可执行文件中相临段的段地址就有可能相同。
为了说明这个问题,我们下面给出了一个程序例:
第一章 基础知识第五章 汇编语言程序结构
*组合类型 (combine_type)设置一定的组合类型就可以通知 LINK程序把一些分散在不同模块内的同类型段组织在一个段内,这样可以使最终形成的可执行文件结构比较清晰。
PUBLIC 该段连接时将与有相同名字的其他分段连接在一起 。 其连接次序由连接命令指定 。
COMMON 该段在连接时与其他同名分段有相同的起始地址,所以会产生覆盖 。
COMMON的连接长度是各分段中的最大长度 。
AT expression 使段的起始地址是表达式所计算出来的 16位段地址 。 但它不能用来指定代码段 。
STOCK 指定该段在运行时为堆栈段的部分 。
MEMORY 指定该段将分配在所有其他连接在一起的段的前面 (在高地址上 ),如果连接时有几个指定 MEMORY的段,则遇到的第一段作为 MEMORY段,其他则作为 COMMON段.
*类别 (‘CLASS’) 连接时用于组成段组的名字:
可以是:
第一章 基础知识第五章 汇编语言程序结构四、程序开始和结束伪操作 (ASM操作规则 )
在程序的开始可以用 NAME或 TITLE为模块取名字,NAME的格式是:
NAME module_name
汇编程序将以给出的 module_name作为模块的名字 。 如果程序中没有 NAME伪操作,则也可使用 TITLE伪操作,其格式为;
TITLE text
TITLE 伪操作可指定每一页上打印的标题。同时,如果程序中没有使用 NAME
伪操作.则程序将用 text中的前六个字符作为模块名。 text最多可有 60个字符。
如果程序中既无 NAME又无 TITLE伪操作,则将用源文件名作为模块名 。所以
NAME及 TILLE伪操作并不是必要的,
表示源程序结束的伪操作的格式为,
其中标号指示程序开始执行的起始地址。 如果多个程序模块相连接,则只有主程序要使用标号,其它子程序模块则只用 END而不必指定标号。
第一章 基础知识第五章 汇编语言程序结构五、对准伪操作
* EVEN的操作,
使下一个字节地址成为偶数。一个字的地址最好从偶地址开始,所以对于字数组为保证其从偶地址开始,可以在它前面用 EVEN伪操作来达到这一目的。
例如:
* ORG Constant expression
如常数表达式的值为 n,则 ORG伪操作可以使下一个字节的地址成为常数表达式的值 n。例,
第一章 基础知识第五章 汇编语言程序结构则 VECT1的偏移地址值为 0AH,而 VECT2的偏移地址值为 14H。
在汇编程序对源程序汇编的过程中,使用地址计数器来保存当前正在汇编的指令的地址 。 地址计数器的值可用 $来表示,汇编语言允许用户直接用 $来引用地址计数器的值,因此
ORG $+8
可以表示跳过 8个字节的存储区。
第一章 基础知识第五章 汇编语言程序结构在指令和伪操作中 也可以直接用 $来表示地址计数器的值,如
JNE $+6
则转向地址是 JNE指令的首地址加上 6。在这里,$十 6必须是另一条指令的首地址,否则,汇编程序指示出错信息。 当 $用在伪操作的参数字段时,则和用在指令中的情况不同,它表示的是 地址计数器的当前值 。
如汇编时 ARRAY分配的偏移地址为 0074H,则汇编后的存 储区将如右图所示 。 应该注意,
ARRAY数组中的两个 $ 十 4得到的结果是不同的,
这是由于 $的值是在不断变化的缘故 。 当在指令中用到 $时,它只代表该指令的首地址,而与 $本身所在的字节无关 。
第一章 基础知识第五章 汇编语言程序结构六、基数控制伪操作汇编程序默认的是十进制数,为此,当使用其他基数表示的常数时,需要专门给以标记如下:
l 二进制:后面跟字母 B
l 十进制:默认,后面也可以跟字母 D
l 十六进制:后面跟字母 H,如果第一个字母是 A-F时,应在其前面加上数字 0
l 八进制:后面跟 O或 Q。
·RADIX伪操作,可以把 默认的基数 改变为 2– 16范围内的任何基数 。 格式如下:
·RADIX expression
字符串可以看成串常数,可以用单引号或双引号把字符串放在其中,得到的是字符串的 ASC码值,例如 ‘ ABCD’。
第一章 基础知识第五章 汇编语言程序结构第三节:汇编语言程序格式汇编语言源程序中的每个语句可以由四项组成,格式如下:
其中:
名字项是 —个符号 。
操作项是一个操作码的助记符,它可以是指令,伪操作或宏指令名 。
操作数项由一个或多个表达式组成,它提供为执行所要求的操作而需要的信息 。
注释项用来说明程序或语句的功能。为识别注释项的开始。也可以从一行的第一个字节开始,此时整行都是注释,常用来说明下面一段程序的功能。
一 名字项源程序中用下列字符来表示名字字母 A— Z
数字 0 — 9
专用字符?,·、@、一,$
第一章 基础知识第五章 汇编语言程序结构注意,( 1) 除数字外,所有字符都可以放在源语句的第一个位置 。
( 2) 名字中如果用到 ·则必须是第一个字符 。
( 3)可以用很多字符来说明名字,但只有前面的 31个字符能被汇编程序所识别。
用途:名字项可以是标号或变量。它们都用来表示本语句的符号地址,它是可有可无的,只有当需要用符号地址来访问该语句时它才需要出现。
·标号,标号在代码段中定义,后面跟冒号:,它也可以用 LABEL或 EQU伪操作来定义 。 此外它还可以作为过程名定义 。 标号经常在转移指令或 CALL指令的操作数字段出现,用以表示转向地址 。
标号有三种属性;段、偏移及类型。
段属性,定义标号的段起始地址,此值必须在一个段寄存器中 。 而标号的段则总是在 CS寄存器中 。
偏移属性,标号的偏移地址是 16位无符号数,它代表从段起始地址到定义标号的位置之间的字节数 。
类型属性,用来指出该标号是在本段内引用还是在其它段中引用的。如在段内引用的,则称为 NEAR,指针长度为 2字节:如在段外引用,则称为 FAR,指针长度为 4字节。
第一章 基础知识第五章 汇编语言程序结构
·变量,变量在除代码段以外的其他段中定义,后面不跟冒号。它也可以用
LABEL或 EQU伪操作来定义。变量经常在操作数字段出现。它也有段、偏移及类型三种属性。
段属性,定义变量的段起始地址,此值必须在一个段寄存器中 。
偏移属性; 变量的偏移地址是 16位无符号数,它代表从段的起始地址到定义变量的位置之间的字节数 。 在当前段内给出变量的偏移值等于当前地址计数器的值,
当前地址计数器的值可以用 $来表示 。
类型属性; 变量的类型属性定义该变量所保留的字节数 。 如 BYTE(1个字节长 )、
WORD(2个字节长 ),DWORD(4个字节长 ),DQ(8个字节长 ),DT(10个字节长 ),
这一点在数据定义伪操作中已作了说明 。
在程序中同样的标号或变量的定义只允许出现一次,否则汇编程序会指示出错。
二、操作项操作项可以是指令、伪操作或宏指令的助记符。对于指令,汇编程序将其翻译为机器语言指令。对于伪操作.汇编程序将根据其所要求的功能进行处理。对于宏指令,则将根据其定义展开。这在以后中将专门论述。
第一章 基础知识第五章 汇编语言程序结构三、操作数项操作数项由一个或多个表达式组成,多个操作数项之间一般用逗号分开。对于指令,操作数项一般给出操作数地址,它们可能有一个或二个或一个也没有。
对于伪操作或宏指令则给出它们所要求的参数。
操作数项可以是常数、寄存器、标号、变量或由表达式组成。
表达式是常数、寄存器、标号、变量与一些操作符相组合的序列,可以有数字表达式和地址表达式两种。在汇编期间,汇编程序按照一定的优先规则对表达式进行计算后可得到一个数值或一个地址。
(一 )算术操作符算术操作符有十、一,*、/和 MOD。其中 MOD是指除法运算后得到的余数,如 19/ 7的商是 2,而 19 MOD 7则为 5(余数 )
算术操作符可以用于数字表达式或地址表达式中,但当它用于地址表达式时,只有当其结果有明确的物理意义时其结果才是有效的。例如两个地址相乘或相除是无意义的。
第一章 基础知识第五章 汇编语言程序结构例,如要求把首地址为 BLOCK的字数组的第 6个字传送到 DX寄存器,可用指令
M0V DX,BLOCK十 (6 - 1)*2
例,如数组 ARRAY定义,如下试写出把数组长度 (字数 )存入 CX寄存器的指令 。
ARRAY DW 1,2,3,4,5,6,7
ENDB DW?
其中 END是为计算数组长度而建立的符号地址,所需指令如下
MOV CX,(ENDB—ARRAY)/ 2
汇编程序在汇编期间将计算表达式而形成指令
MOV CX,7
(二 )逻辑操作符它有 AND,OR,XOR和 NOT。逻辑操作符是按位操作的,它只能用于数字表达式中。
第一章 基础知识第五章 汇编语言程序结构例:
其中 PORT_VAL为端口号,OUT指令中的表达式说明当 PORT_VAL为偶数时,输出端口号与输入端门号相同,而当 PORT_VAL为奇数时,输出瑞口号比输入端口号小 1。
(三 )关系操作符它有 EQ(相等 ),NE(不等 ),LT(小于 ),GT(大于 ),LE(小于或等于 ),GE(大于或等于 )6种。
关系操作符的两个操作数必须都是数字或是同一段内的两个存储器地址。计算的结果应为逻辑值:结果为真,表示为 0FFFFH,结果为假,则表示为 0。
例:
则当 PORT_VAL< 5时,汇编结果应该是:
MOV BX,20
否则,汇编结果应该是:
MOV BX,30
第一章 基础知识第五章 汇编语言程序结构
(四 )数值回送操作符它有 TYPE,LENGTH,SIZE,OFFSET,SEG 5种。这些操作符把一些特征或存储器地址的一部分作为数值回送。
* TYPE
格式为,TYPE Variable 或 label
如果是变量,则汇编程序将回送该变量的以字节数表示的类型,DB为 1,DW为
2,DD为 4,DQ为 8,DT为 10。 如果是标号,则汇编程序将回送代表该标号类型的数值,NEAR为 -1,FAR为 -2。
例,ARRAY DW 1,2,3
……
ADD SI,TYPE ARRAY
汇编程序将这个指令形成为:
ADD SI,2
第一章 基础知识第五章 汇编语言程序结构
* LENGTH
格式为,LENGTH Variable
对于变量中使用 DUP的情况,汇编程序将回送分配给该变量的单元数。而对于其他情况则回送 1。
例 FEES DW 100 DUP(0)
MOV CX,LENGTH FEES
汇编程序将对于指令形成为,MOV CX,100
例 ARRAY DW 1,2,3
MOV CX,LENGTH ARRAY
汇编程序将对于指令形成为,MOV CX,1
例 TABLE DB ‘ABCD’
MOV CX,LENGTH TABLE
汇编程序将对于指令形成为; MOV CX,l
第一章 基础知识第五章 汇编语言程序结构
* SIZE
格式为,SIZE Variable
汇编程序应回送分配给该变量的字节数。但是,此值是 LENGTH值和 TYPE
值的乘积 。
对于上述例子的情况:
MOV CX,SIZE ARRAY
将形成为 MOV CX,2
MOV CX,SIZE TABLE
将形成为 MOV CX,1
*OFFSET
格式为,OFFSET Variable 或 label
汇编程序将回送变量或标号的偏移地址值 。与 LEA 具有相同功能。
MOV BX,OFFSET OPEN_ONE
LEA BX,OPER_ONE
第一章 基础知识第五章 汇编语言程序结构
* SEG
格式为,SEG Variable 或 Label
汇编程序将回送变量或标号的段地址值,
例 如果 DATA_SEG是从存储器的 05000H地址开始的一个数据段的段名,OPERl
是该段中的一个变量名,则
MOV BX,SEG OPER1
将把 0500H作为立即数插入指令。实际上由于段地址是由连接程序分配的,
所以该立即数是连接时插入的。执行期间则使 BX寄存器的内容成为 0500H。
(五 )属性操作数 符有 PTR、段操作符,SHORT,THIS,HIGH和 LOW 6种。
格式为,type PTR expression
第一章 基础知识第五章 汇编语言程序结构
PTR用来建立一个符号地址,但它本身并不分配存储器,只是用来给已分配的存储地址赋予另一种属性,使该地址具有另一种类型。
格式中的类型字段表示所赋予的新的类型属性,而表达式字段则是被取代类型的符号地址。
例 已有数据定义如下:
可以用以下语句对这两个字节赋予另一种类型定义:
后者也可以写成;
这里 ONE_BYTE和 TWO_BYTE两个符号地址具有相同的段地址及偏移地址,但是它们的类型属性不同,前者为 1,后者为 2。
第一章 基础知识第五章 汇编语言程序结构类型可有 BYTE,WORD,DWORD,NEAR和 PAR几种,所以 PTR也可以用来建立字、双字或段内及段间的指令单元。
例如,MOV [BX],5
指令把立即数存入 BX内容指定的存储单元中,但汇编程序不能分清是存入字单元还是字节单元,此时必须用 PTR操作符来说明属性,应该写明:
MOV BYTE PTR [BX],5
或 MOV WORD PTR [BXl,5
* 段操作符,用来表示一个标量、变量或地址表达式的段属性。例如,用段前缀指定某段的地操作数
MOV AX,ES,[BX+SI]
格式 段寄存器:地址表达式
* SHORT,用来修饰 JMP指令中转向地址的属性,指出转向地址是在下一条指令地址的 ± 127个字节范围之内。
第一章 基础知识第五章 汇编语言程序结构
* THIS,格式为,THIS attribute 或 type
它可以象 PTR一样建立一个指定类型 (BYTE,WORD或 DWORD)的或指定距离 (NEAR或 FAR)的地址操作数 。 该操作数的段地址和偏移地址与下一个存储单元地址相同 。 例如:
此时 FIRST_BYTE的偏移地址值和 WORD_TABLE完全相同,但它是字节类型的,而 WORD_TABLE则是字类型的。
又如,START EQU THIS FAR
MOV CX,l00
MOV指令有一个 FAR属性的地址 START,这就允许其它段的 JMP指令直接跳转到 START来。
* HIGH和 LOW
称为字节分离操作符字节。它接收一个数或地址表达式,HIGH取其高位字节,LOW取其低位字节。
第一章 基础知识第五章 汇编语言程序结构例如:
我们知道表达式是常数、寄存器、标号、变量和操作符的组合,在计算表达式值时,应该首先计算优先级高的操作符,然后从左到右地对优先级相同的操作符进行计算。括号也可以改变计算次序,括号内的表达式应优先计算。
下面给出操作符的优先级别 (其中有些操作符我们并未提到过,需要时可从手册中查到 ),从高到低排列如下:
第一章 基础知识第五章 汇编语言程序结构
(六 )注释注释项用来说明一段程序或一条或几条指令的功能,它是可有可无的。但是,对于汇编语言程序来说,注释项的作用是很明显的,它可以使程序易于被读懂,因此,编制程序必须写好注释。
根据上面介绍的内容,这里给出一个汇编完整的例子来说明汇编语言的编程框架和结构。
例:从键盘输入字符并将输入的字符显示出来,如果输入是英文字符小写字母,将小写字母转换成为大写字母。
data segment
message db 'This is a sample program of keyboard and disply'
db 0dh,0ah,'Please strike the key!',0dh,0ah,'$'
data ends;定义数据段,数据段给出提示内容。在数据段中 0dh和 0ah分别表示回车和;换行字符。字符‘ $’表示字符串的结束标志。如果没有回车和换行会出现什;么显示结果。
第一章 基础知识第五章 汇编语言程序结构
stack segment stack
db 50 dup(?)
stack ends;定义堆栈段。其中 参数 stack表示程序在运行过程中,该段为系统堆栈段中;的一部分。如果不加这个,将单独对本程序建立堆栈。
code segment
assume cs:code,ds:data,ss:stack;明确段寄存器与段定义之间的关系
start,mov ax,data
mov ds,ax
mov ax,stack;可以省,为什么?
mov ss,ax ;可以省,为什么?;初始化段寄存器第一章 基础知识第五章 汇编语言程序结构
mov dx,offset message
mov ah,9
int 21h;显示字符串。调用 21H中断(也是 DOS功能调用)的 9号功能,该功能是;显示字符串,其中 DS,DX为字符串地址,‘ $’为字符串结束标志。
again,mov ah,1
int 21h;调用 21H中断的 1号功能,将键盘输入的字符 ASC码存在 al寄存器
cmp al,1bh;和 ESC键输入字符对比
je exit;如果是按下 ESC键,就跳转结束
cmp al,61h;和’ a’字符对比
jc nd;产生借位,就是小于‘ a’字符,跳转到 nd直接输入结果
cmp al,7ah;和’ z’字符对比
ja nd; 没有借位同时不为零,大于‘ z’字符,跳转到 nd直接输入结果第一章 基础知识第五章 汇编语言程序结构
and al,11011111b;如果输入字符在‘ a’与‘ z’之间,通过与运算,将小写转;换为大写。 Sub al,’ a’-’ A’也一样
nd,mov dl,al;将字符传入到 dl寄存器中
mov ah,2
int 21h;调用 21中断的功能 2,将 dl寄存器的字符输出
jmp again;循环执行,直到按下 ESC键退出
exit,mov ah,4ch
int 21h;调用 21中断的 4ch功能,返回 dos
code ends;代码段结束
end start;结束汇编,程序结束如果将主程序建立为过程,由 DOS调用该过程 。 进入程序后,首先把 DS的内容和 0作为段地址和偏移地址入栈,以便在程序结束时用 RET指令返回 DOS,这是一种较好的工作方式 。 如果在主程序开始时没有用上面三条指令在堆栈中建立返回信息,则在程序结束时效不能直接用 RET返回指令,而应该使用编号为 4c的功能调用返回 DOD。 程序改为如下 。
第一章 基础知识第五章 汇编语言程序结构
data segment
message db 'This is a sample program of keyboard and disply'
db 0dh,0ah,'Please strike the key!',0dh,0ah,'$'
data ends
stack segment stack
db 50 dup(?)
stack ends
code segment
assume cs:code,ds:data,ss:stack
main proc far
start:
push ds
xor ax,ax
第一章 基础知识第五章 汇编语言程序结构
push ax
mov ax,data
mov ds,ax
mov ax,stack
mov ss,ax
mov dx,offset message
mov ah,9
int 21h
again,mov ah,1
int 21h
cmp al,1bh
je exit
cmp al,61h
第一章 基础知识第五章 汇编语言程序结构
jc nd
cmp al,7ah
ja nd;and al,11011111b
sub al,'a'-'A'
nd,mov dl,al
mov ah,2
int 21h
jmp again
exit,ret
main endp
code ends
end start
第一章 基础知识第五章 汇编语言程序结构汇编语言程序上机过程实验目的,
1,掌握常用工具软件 MASM和 LINK的使用 。
2,伪指令,SEGMENT,ENDS,ASSUME,END,OFFSET,DUP。
3,利用的 1号功能实现键盘输入的方法 。
4,用 INT 21H 4C号功能返回系统的方法 。
程序,
1,键盘输入字符并输出,大写转换为小写输出 。
2,将字符串 ‘’ This is a program ’用十六进制显示出来
3,将寄存器 BX中的数据以 ASC码的形式显示实验步骤,
1,用用文字编辑工具 ( 记事本或 EDIT) 将源程序输入,其扩展名为,ASM。
2,用 MASM对源文件进行汇编,产生,OBJ文件和,LST文件 。 若汇编时提示有错,用文字编辑工具修改源程序后重新汇编,直至通过 。
3,用 TYPE命令显示 1产生的,LST文件 。
4,用 LINK将,OBJ文件连接成可执行的,EXE文件 。
5、在 DOS状态下运行 LINK产生的。 EXE文件。
实验报告,
1,汇编,连接及调试时产生的错误,其原因及解决办法 。
2,思考,
若在源程序中把 INT 21H的 'H'省去,会产生什么现象?