本章主要教学内容
,汇编语言和汇编程序的基本概念
,伪指令语句的格式、功能及应用
,汇编语言源程序书写规则、语句格式及程序分段
,汇编语言源程序的建立、汇编、连接、调试及运行
,程序设计方法第 4章 汇编语言程序设计第 4章 汇编语言程序设计本章教学目的及要求
l 理解汇编语言和汇编程序的概念、特点及其应用。
l 掌握汇编语言源程序的书写规则、语句的基本格式、
程序的分段结构。
l 熟悉汇编语言的基本表达、伪指令语句及其应用。
l 熟悉汇编语言程序的上机运行、调试过程,掌握基本操作技能。
l 能够独立编写和分析汇编程序
1 汇编语言和汇编程序的基本概念第 4章 汇编语言程序设计
2 汇编语言源程序书写格式
3 8086汇编语言中的标识符,表达式和运算符
5 DOS功能调用
4 伪指令语句
6 汇编语言程序设计基础
4.1 汇编语言和汇编程序的基本概念
1,汇编语言汇编语言是一种介于 机器语言 和 高级语言 之间的计算机编程语言,是一种面向机器的语言。它和机器码有一一对应的关系,所以允许程序员用汇编语言直接对寄存器、存储器,I/O端口以及 CPU内部的许多硬件进行操作,因此用汇编语言可以编写出高质量的程序,用汇编语言编写的程序占用内存少,
执行速度快。
机器码指令构成的指令系统叫机器语言(二进制代码)。机器语言是能被计算机识别的惟一语言。
例如:
MOV AX,im ( B8)
MOV DX,im ( BA)
MOV CX,im ( B9)
MOV BX,im ( BB)
PUSH AX ( 50)
PUSH DX ( 52)
PUSH CX ( 51)
PUSH BX ( 53)
POP AX ( 58) POP DX ( 5A)
POP CX ( 59) POP BX ( 5B)
汇编语言程序必须先翻译成机器语言程序才能执行。
由汇编语言程序翻译成机器语言程序的过程,
称为 汇编。 完成汇编过程的系统程序称为 汇编语言程序 或称为 源程序。
汇编语言程序翻译 机器语言程序执行
2,汇编程序用汇编语言编写的源程序在输入计算机后,需要将其翻译成目标程序,计算机才能执行相应指令,这个翻译过程称为汇编,完成汇编任务的程序称为汇编程序 。
有 基 本 汇 编 ASM ( Assembler ) 和 宏 汇 编 MASM
( MacroAssembler) 两种 。
汇编程序以汇编语言源程序文件作为输入,并由它产生两种输出文件:目标程序文件和源程序列表文件 。
目标程序文件经连接定位后由计算机执行;
源程序列表文件将列出源程序,目标程序的机器语言代码及符号表 。
汇编程序
ASM 小汇编
MASM 宏汇编推荐两个汇编网站
http://www.x86asm.com
http://www.aogosoft.com
3,汇编语言源程序的结构一般来说,一个完整的汇编源程序应由三个程序段组成,即代码段、数据段和堆栈段,每个段都以 SEGMENT开始,以 ENDS结束,代码段包含程序要执行的指令;堆栈段用来在内存中建立一个堆栈区;数据段用来在内存中建立一个适当容量的工作区,以存放程序中所需的数据。
注意:一个源程序中,代码段是必须的,而数据段和堆栈段可以没有或有其中一个。段定义时一般最后定义代码段。
STACK SEGMENT PARA STACK ‘STACK’
DB 500 DUP( 0)
STACK ENDS
DATA SEGMENT
DATA ENDS
CODE SEGMENT
MAIN PROC FAR
ASSUME CS,CODE,DS,DATA,
ES,DATA,SS,STACK
PUSH DS
MOV AX,0
PUSH AX
MOV AX,DATA
MOV DS,AX
MOV ES,AX
RET
MAIN ENDP
CODE ENDS
END MAIN
定义堆栈段定义数据段定义代码段
SEG ENT
SEG ENT
ENDS
SEGMENT
ENDS
I PR C
MAIN ENDP
END
例 4-1 编写一个两字相加的程序
DSEG SEGMENT
DATA1 DW 0F865H
DATA2 DW 360CH
DSEG ENDS
ESEG SEGMENT
SUM DW 2 DUP(?)
ESEG ENDS
CSEG SEGMENT
ASSUME CS,CSEG,DS,DSEG,ES,ESEG
START,MOV AX,DSEG
MOV DS,AX
MOV AX,ESEG
MOV ES,AX
LEA SI,SUM
MOV AX,DTTA1
ADD ES,[SI],AX
HLT
CSEG ENDS
END START
代码段,CODE
数据段,DATA
堆栈段,STACK
4.1.2 汇编语言源程序的语句类型和语句格式
1.语句类型
8086宏汇编 MASM使用的语句可以分成 3种类型:
指令语句:这类指令能够产生目标代码,是 CPU可以执行的能够完成特定功能的语句,主要由机器指令组成。在汇编时一条指令语句被翻译成对应的机器码,对应着特定的操作。
伪指令语句:伪指令语句是为汇编程序和连接程序提供一些必要控制的管理性语句,它不产生目标代码,仅仅在汇编过程中告诉汇编程序应如何汇编,并完成相应的伪操作。
宏指令语句:宏指令语句是由编程者按照一定的规则来定义的一种较,宏大,的指令,可包括多条指令或伪指令 。
2,语句格式一般情况下,汇编语言的语句可以由 以下几 部分组成:
[名字 ] 操作码 [操作数 ] [;注释 ]
名字是一个符号,它表示本条语句的符号地址 。 一般来说,名字可以是标号和变量,统称为标识符 。
注意:标号和变量都具备 3种属性 —— 段属性,偏移属性及类型属性 。
操作码可以是机器指令,伪指令和宏指令的助记符 。
操作数字段是操作码的操作对象 。 操作码在完成相应的操作时要求有一系列的操作数 。 当有两个或两个以上的操作数时,各操作数之间用逗号隔开 。
注释字段是以,;,开头的说明部分,可以用英文或者中文书写 。 注释字段是语句的非执行部分 。
4.1.3 8086汇编语言中的标识符,表达式和运算符
1,标识符 ( 标号,变量,名字 )
汇编语言每条语句的第一个字段是它的名字字段,名字可以是标号或变量,这两者又称为标识符 。
重点是要掌握其组成规则和它的 3个属性 。
2,表达式和运算符在表达式中,运算符充当着重要的角色 。
8086宏汇编有算术运算符,逻辑运算符,关系运算符,分析运算符和综合运算符共 5种 。
下面分别讨论 5种运算符的作用:
DSEG SEGMENT
DATA1 DW 0F865H
DATA2 DW 360CH
DSEG ENDS
ESEG SEGMENT
SUM DW 2 DUP(?)
ESEG ENDS
CSEG SEGMENT
ASSUME CS,CSEG,DS,DSEG,ES,ESEG
START,MOV AX,DSEG
MOV DS,AX
MOV AX,ESEG
MOV ES,AX
LEA SI,SUM
MOV AX,DTTA1
ADD ES,[SI],AX
HLT
CSEG ENDS
END START
( 1)算术运算符用于完成算术运算,有+
(加法)、-(减法),× (乘法)、/(除法)、
MOD(求余),SHL(左移),SHR(右移)共 7
种运算。
( 2)逻辑运算符的作用是对其操作数进行按位操作。逻辑运算符有 AND(与),OR(或),XOR
(异或)和 NOT(非)。
( 3)关系运算符的运算对象是两个性质相同的项目。其结果为:关系成立或不成立。有 EQ(相等),NE(不相等),LT(小于),GT(大于)、
LE(小于或等于),GE(大于或等于)共 6种。
( 4)分析运算符是对存储器地址进行运算的。
有 5个,SEG(求段基值),OFFSET(求偏移量),
TYPE(求变量类型),LENGTH(求变量长度) 和
SIZE(求字节数) 。
( 5) 综合运算符可以用来建立和临时改变变量或标号的类型以及存储器操作数的存储单元类型,
而忽略当前的属性,所以又称为属性修改运算符。
有 6个综合运算符,PTR、段属性前缀,SHORT、
THIS,HIGH 和 LOW。
4-2 伪指令语句在汇编语言中,伪指令是给汇编程序的命令,
在汇编过程中由汇编程序进行处理。
例如定义数据、分配存储区、定义段及定义过程等都采用伪指令表示。
4.2.1 数据定义伪指令数据定义伪指令用来定义一个变量的类型,
并将所需要的数据放入指定的存储单元中,也可以只给变量分配存储单元,而不赋予特定的值。
1,数据定义伪指令的一般格式为:
[变量名 ] 伪指令 操作数 [,操作数 … ][;注释 ]
2,常用的 数据定义伪指令
定义字节变量伪指令 DB
定义字变量伪指令 DW
定义双字变量伪指令 DD
定义四字变量伪指令 DQ
定义十字节变量伪指令 DT
例,DATA1 DB 5,6,7
DATA2 DW 1,2,1A34H
DATA3 DD 5,6,1A34H
DATA1 05
06
07
DATA2 01
00
02
00
34
1A
DATA3 05
00
00
00
06
定义重复变量伪指令 DUP
格式:

DATA1 DB 10 DUP ( 0);定义 DATA1为 10个,0”组成的字节变量
DATA2 DW 2 DUP (?);定义 DATA2为 2个不确定数值的字变量
DATA3 DB 4 DUP ( 1,2 DUP( 50H));定义 DATA3为( 1,50H,50H)重复 4次共 12个字节的字节变量
DB
DW
DD
变量名 n DUP (表达式)
4.2.2 符号定义伪指令符号定义伪指令的用途是给一个符号重新命名,
或定义新的类型属性等 。 这些符号可以包括汇编语言的变量名,标号名,过程名,寄存器名以及指令助记符等 。
常用的符号定义伪指令有 EQU,=,LABLE。
4.2.3 段定义伪指令一个完整的源程序由 3个段组成:堆栈段、数据段、
代码段。
SEGMENT:定义一个段开始。一个段必须有一个名称来标识。
ENDS:说明一个段的结束,和 SEGMENT成对使用。
格式,段名 SEGMENT [定位类型 ] [组合类型 ] [类别 ]
段名 ENDS
4.2.4 ASSUME 段分配伪指令格式,ASSUME 段寄存器:段名 [,段寄存器:段名,……]
用于说明源程序中定义的段或组由哪个寄存器去寻址,即建立寄存器与段间的对应关系。
例:
CODE SEGMENT
ASSUME CS,CODE,DS,DATA,SS,STACK
MOV AX,DATA
MOV DS,AX
CODE ENDS
4.2.5 定义过程的伪指令 PROC和 ENDP
过程:具有一定功能的程序段(相当于一个子程序)
格式,过程名 PROC [类型 ]
RET
过程名 ENDP
说明,过程体内应至少有一条 RET指令,以便返回被调用处。一个过程可以调用另一个过程,
也可以调用过程本身。
举例:
FAR
NEAR
一个延时 100ms 的子程序,过程定义为:
SOFTDLY PROC
MOV BL,10
DELAY,MOV CX,2801
WAIT,LOOP WAIT
DEC BL
JNZ DELAY
RET
SOFTOLY ENDP
PUSH BX
PUSH CX
POP CX
POP BX
小循环大循环宏定义格式:
宏指令名 MACRO [ 形式参量 1,形参 2,……]
ENDM
宏指令名是一个宏调用的依据(必须要写,与标号规定一致)
[ 形式参量表 ] 可有可无,可以是一个,也可以有多个,
在有多个时,各参量之间应用逗号分开。
宏定义符 MACRO和宏定义结束符 ENDM成对出现。
宏体,MACRO~~ENDM之间。
宏体
4.2.6 宏命令伪指令宏调用格式:
宏指令名 [ 实参 1,实参 2,……… ]
宏调用中的实参应与宏定义中的形参一一对应,但在 IBM宏汇编中,数量上不一定一致,若实参多于形参,则多余部分被忽略,若实参少于形参,则多余的形参按空对待。
例,若对 AL中的数据进行算术左移 4位的操作,在某程序中被多次使用,可对该指令组进行宏定义。
SHIFT MACRO
MOV CL,4
SAL AL,CL
ENDM
宏体
MOV AL,02H
SHIFT
例:用宏定义一个梯形面积公式。设上底为 x,
下底为 y,高为 h x
y
h
MOV AL,X
ADD AL,Y
MOV BL,H
MUL BL
SHR AX,1
MOV AREA,AX
TAREA MACRO X,Y,h,AREA
ENDM
现已知一梯形上底为 8,下底为 10,高为 5。求此梯形面积。
MOV AL,08H
ADD AL,0AH
MOV BL,05H
MUL BL
SHR AX,1
MOV BX,AX
TAREA 08H,0AH,05H,BX,34H
4.2.7 模块定义与连接伪指令在编写规模较大的汇编语言源程序时,可以将整个程序划分为几个独立的源程序,称之为模块 。
将各模块分别进行汇编,生成各自的目标程序,
最后将它们连接成为一个完整的可执行程序 。
各模块之间可以相互进行符号访问 。
为了进行模块之间连接和实现相互的符号访问,
以便进行变量传送,通常使用以下几个伪指令:
NAME,END,PUBLIC。
不同的寻址方式的灵活应用
[idata] 用一个常量来表示地址,可用于直接定位一个内存单元。 例,[1000h]
[bx] 用一个变量来表示内存地址,可用于间接定位一个内存单元。
[bx+idata] 用一个变量和常量表示地址,可在一个起始地址的基础上用变量间接定位一个内存单元。
[bx+si] 用两个变量表示地址。
[bx+si+idata] 用两个变量和一个常量表示地址。
编程,将 data段中每个单词的头一个字母改为大写字母。
assume cs:code,ds:data
data segment
db ‘1,file ’
db ‘2,edit ’
db ‘3,search ’
db ‘4,view ’
db ‘5,options ’
db ‘6,help ’
data ends
code segment
start:
0 1 2 3 4 5 6 7 8 9 A B C D E F
0000 1,f i l e
0010 2,e d i t
0020 3,s e a r c h
0030 4,v i e w
0040 5,o p t i o n s
0050 6,h e l p
编程,将 data段中每个单词改为大写字母。
assume cs:code,ds:data
data segment
db ‘ibm ’
db ‘dec ’
db ‘dos ’
db ‘vax ’
data ends
code segment
start:0 1 2 3 4 5 6 7 8 9 a b c d e f
0000 i b m
0010 d e c
0020 d o s
0030 v a x
0040
start,mov ax,data
mov ds,ax
mov bx,0
mov cx,4
s1,mov dx,cx
mov si,0
mov cx,3
s2,mov al,[bx+si]
and al,0dfh
mov [bx+si],al
inc si
loop s2
add bx,16
mov cx,dx
loop s1
编程,将 data段中每个单词的前四个字母改为大写字母。
assume cs:code,ds:data,ss:stack
stack segment
dw 0,0,0,0,0,0,0,0
stack ends
data segment
db ‘1,display ’
db ‘2,brows ’
db ‘3,replace ’
db ‘4,modify ’
data ends
code segment
start:
0 1 2 3 4 5 6 7 8 9 a b c d e f
0000 1,d i s p l a y
0010 2,b r o w s
0020 3,r e p l a c e
0030 4,m o d i f y
在存储器系统中,内存器高端 8K的 ROM中存放有基本输入输出系统 ( Basic Input/Output System,BIOS)
例行程序 。 BIOS给 PC系列的不同微处理器提供了兼容的系统加电自检,引导装入,主要 I/O设备的处理程序以及接口控制等功能模块来处理所有的系统中断 。 使用
BIOS功能调用,给程序员编程带来极大方便 。 程序员不必了解硬件的具体细节,可直接使用指令设置参数,
并中断调用 BIOS例行程序,所以利用 BIOS功能调用编写的程序简洁,可读性好,而且易于移植 。
4.3 DOS系统功能调用磁盘操作系统( Disk Operating System)是 PC机上最重要的操作系统,它是由软盘或硬盘提供的。它的两个 DOS模块 IBMBIO.COM和 IBMDOS.COM使
BIOS使用起来更方便。因为 DOS模块提供了更多更必要的测试,使 DOS操作比使用相应功能的 BIOS操作更简易,而且 DOS对硬件的依赖性更少些。 DOS模块和
ROM BIOS的关系如下图所示。
功能调用号?AH
置入口参数执行,INT 21H,
分析出口参数


系统功能调用的方法
DOS功能调用与 BIOS功能都通过软件中断调用。在中断调用前需要把功能号装入 AH寄存器,把子功能号装入 AL寄存器,除此之外,还需要在 CPU的寄存器中提供专门的调用参数。一般来说,调用 DOS或
BIOS功能时,有以下几个步骤:
1、键盘单字符输入 (1号调用 )
格式,MOV AH,1
INT 21H
功能,等待从键盘输入一个字符并将输入字符的 ASCII码 送入寄存器
AL中,碰到 CTRL+Break则退出 。
2、显示输出 (2号调用 )
格式,MOV AH,2
MOV DL,待显字符的 ASCII码
INT 21H
功能,将 DL中的字符送显示器显示,若为 CTRL+Break的 ASCII码 则退出 。
3、键盘输入字符串 (10号调用 )
格式,LEA DX,缓冲区首偏移地址
MOV AH,10
INT 21H
功能,从键盘上往指定缓冲区中输入字符串并送显示器显示 。
如,BUF DB 81
DB?
DB 80 DUP (0)
注,缓冲区应按规定的格式定义。
BUF第一字节规定了缓冲区的大小,从键盘输入的字符串从第三个字节存放,第二个字节存放实际输入的字符个数 。
例 4-9从键盘上输入字符串‘ HELLO’,并在串尾加结束标志‘ $’
DATA SEGMENT
STRING DB 10,0,10 DUP(?) ;定义缓冲区
DATA ENDS
CODE SEGMENT
ASSUME CS,CODE,DS,DATA
MOV AX,DATA
MOV DS,AX ;数据段初始化
LEA DX,ATRING ;取缓冲区偏移地址
MOV AH,0AH ;功能号输入
INT 21H ; DOS功能调用
MOV CL,STRING+1 ;取字符个数
XOR CH,CH
ADD DX,CX ;得到字符串尾地址
MOV BX,DX
MOV BYTE PTR [BX+2],‘ $’
MOV AH,4CH
INT 21H ;返回 DOS
CODE ENDS
END START
屏幕显示程序举例屏幕显示程序举例
内存地址空间 B8000H— BFFFFH共 32KB为 25
行 × 80列的彩色字符模式显示缓冲区。
显示器每屏可显示 25× 80=2000个字,其中每个字占 2个字节,低字节为符号,高字节为字符属性。显示缓冲区可分 8页显示,默认情况下从第 0页开始显示。
屏幕显示位置与内存地址的关系
:0,1,2,3,50,51,9e,9f
B800:0 0 1 2 3 4 80 81 158 159
:A0 1
:140 2
:1E0 3
:280 4
5
:780 12,7D0
:DC0 23
:E60 24
:F00 25
例:第 4行,第 2列
PA=B8000+A0× 4+(2× 2)
=B8000+280+4
=B8284H
第 M 行,第 N 列的地址为,
PA=B8000H+M × A0H+2× N
显示缓冲区中,内容的描述
:0,1,50,51,9e,9f
1 2 81 82 159 160
B800:0 1
:A0 2
:780 13 ‘A’ 76H
:F00 25
每个字在内存中占用 2字节,低字节(偶地址)为字符内容,高字节(奇地址)为字符属性。
字符属性格式:
7 6 5 4 3 2 1 0
含义 BL R G B I R G B
闪烁 背景 高亮 前景色
编程在屏幕中间分别显示绿色、绿底红色、白底蓝色的字符串,welcome to masm!”
要显示的字符
Data segment
db ‘welcome to masm!’
Data ends
要写入的内存地址:
EA=12× A0H+2× 40=7D0H
Start,mov ax,data
mov ds,ax
mov ax,0b800h
mov es,ax
mov cx,16
mov bx,0
mov di,7d0h
S,mov al,[bx]
mov ah,02
mov es:[di],ax
mov ah,24h
mov es:[di+0a0h],ax
mov ah,71h
mov es:[di+140h],ax
inc bx
add di,2
loop s