当前位置: 首页 > >

2019年-第五章 汇编语言程序的设计(wq)-PPT精选文档_图文

第五章 汇编语言程序设计
? 5.1 汇编语言语句的类型和组成 ? 5.2 伪操作命令

? 5.3 DOS系统功能调用和BIOS中断调用
? 5.4 汇编语言程序设计

第五章 汇编语言程序设计 5.1 汇编语言语句的类型和组成
5.1.1 汇编语言语句的类型
在汇编语言中我们不仅要知道指令系统,而且

还必须了解汇编语言语句的组成和类型,了解汇编
语言中的编写程序的格式以及格式中各个部分的意 义,以便我们能够编写出正确的源程序。 汇编语言有自身的语法规则,汇编语言源程序中有 3种基本语句:

①指令性语句(由CPU指令组成);
②指示性语句(伪指令语句)和宏指令语句。 指令性语句和指示性语句是最基本的语句,也是最常用的语句。 二者的区别是: ①指令性指令是给CPU的命令,它是由汇编程序翻译成机器语

言指令,在程序运行时由CPU来执行,每条指令都对应CPU一
种特定的操作,例如:算术运算、逻辑运算、串操作等;而伪 指令是给汇编程序的命令,伪指令不汇编成机器语言,仅仅在

汇编过程中告诉汇编程序应如何汇编。在汇编中由汇编程序进
行处理,例如:定义数据分配,定义过程等。 ②指令性指令汇编以后,每条指令都产生其对应的机器代码; 而伪指令则不产生与之对应的机器代码。 宏指令是使用者利用上述基本语句自己定义的新的指令。

汇编语言程序结构特点
? 例:5个连续字节单元的累加 段定义语句
DATA SEGMENT D1 CC SUM DB 5 DUP(?) EQU $-D1 DW 0 ;定义数据段 ;连续的字节单元 ;为结果保留一个字 ;数据段定义结束

伪指令 ;对单元计数

定义存储单元 的数据

DATA ENDS DB 100 DUP (?) STACK ENDS

STACK SEGMENT PARA STACK ‘STACK’

作堆栈用的 ;100 字节的栈空间
存储单元 ;堆栈段定义结束
;定义代码段

;定义堆栈段
定义堆栈

CODE SEGMENT
BEGIN:MOV AX,DATA MOV DS,AX

ASSUME DS:DATA,SS:STACK,CS:CODE

;对各段进行说明

;DS初始化为DATA

指令
;预置源数据的指针

LEA SI,D1

MOV CX,CC+1 CLD DEC CX MOV AH,0

;预置次数 ; (DF)=0,串指针自动增量 ;修改次数 ;清AX的高字节

LODS BYTE PTR [SI] ;取一个数并修改指针

CLC
AGAN:ADC SUM,AX

;清CF位
;累加

LODS BYTE PTR [SI] ;再取数并修改指针

LOOP AGAN
MOV AH,4CH INT 21H CODE ENDS END BEGIN

;控制循环
;完成,返回DOS ;代码段结束 ;整个程序结束

段定义

汇编程 序结束

源程序的一般格式
? 代码段是必需的。每段必须有且仅有一个名字,以SEGMENT 定义段的起始,以 ENDS 定义段的结束,整个程序结束后需以 END收尾。源程序的一般格式为: 段名1 SEGMENT 语句 … 语句 段名1 ENDS 段名2 SEGMENT 语句 … 语句 段名2 ENDS … END (标号或过程名)

汇编语言源程序的结构
段名1 SEGMENT 语句行 …… 语句行 段名1 ENDS 段名2 SEGMENT 语句行 …… 语句行 段名2 ENDS …… END 标号或过程名

?一个源程序由若干段组成, 如数据段、代码段、堆栈段等;
?各段由若干条语句行组成;

?指令必须放在代码段中;
?为了确保程序的执行和正确 返回,必须借助堆栈段; ?根据编程需要确定是否需要 数据段、附加段。

5.1.2 汇编语言语句的组成
1.指令性语句:即执行性语句(指令)包括四部分:

[ 标号:]

指令操作码

[ 操作数 ]

[;注释 ]
;累加

例: AGAN:ADC SUM,AX

2.指示性语句:即说明性语句 (伪指令),由四部分组 成: [ 名字 ] 伪指令 [ 操作数 ] [;注释 ]

例:SUM DW 0

;为结果保留一个字

汇编语言的语句行
? 指令性语句 指令,与机器码一一对应。

? 指示性语句
伪指令,可以对源程序进行指示、说明、定义等。

? 注释语句 以分号开始,整行均是对程序的注解,增强可读性。 本身不参与汇编,对指令代码无任何贡献。

汇编语言的语句行构成
? 指令性语句
[指令标号:] 指令助记符 [操作数1[,操作数2]] ;注释 ? 指示性语句——伪指令 [名字] 伪指令助记符 [参数1[,参数2,…,参数n]] ;注释

1、汇编语句的说明
汇编语言中的字符集
?

字符
A~Z或a~z 注:汇编源程序中,大小写字符功能一样

?

数字 0~9

注:数字不用于标识符的第一位
?

特殊符号 ?、/、%等 注:标识符中谨慎使用特殊符号

汇编语言中的保留字
?

汇编源程序中标识符不能使用的字符串 寄存器名 标志符 指令助记符 伪指令符 运算符 例:AX、SP 例:CF、TF 例:MOV、ADD 例:SEGMENT、END 例:OFFSET、PTR

? ? ?

?
?

标识符(标号、符号地址、变量名)
标识符——由编程人员自行定义的、有特殊意义 的字符序列。 ? 标识符的使用
可使用字母、数字、特殊字符(? $ _) ? 不能使用保留字 !符合字符集要求 ? 不用数字开头,第一个符号最好用字母 ? 长度小于 32 个字符
?

? 标识符的作用 ? 用作段名、过程名、结构名、宏名等的定义 ? 用作变量名,数据段符号地址的定义 ? 用作代码段标号

标识符
?

数据段中的标识符
?

符号地址具有存储地址值和数据类型的特征 伪指令前的标号定义——变量 指令前的标号定义——标号:

?

代码段中的标识符
? ?

?

标识符与常量

MOV AL,F8H (AL)=(F8H),从符号地址中取数 MOV AL,0F8H (AL)=F8H,常数F8H赋值

常量
常量——出现在源程序中指令操作数的位置,具有 固定值的数值。
?

整数:必须以数字开头!
二进制数——以“B” 结尾 八进制数——以“O”或“Q” 结尾 十进制数——不带结尾字母,或以“D” 结尾 十六进制数——以“H” 结尾

?

字符串

连续的字节单元,每个单元均存放ASCII码。用包 括在单引号中的字母表示(单引号本身不算作字符)。 如‘ABCDEF’,对应的数值依次是41H~46H。

变量和标号
?变量——编程人员为内存单元起的名字。有3种属性:
? 段基址:该单元所在段的首址,用相应的段寄存器值表示

(16位) ? 偏移量:该单元在段内的偏移量或有效地址,表示与段首地 址之间的距离(16位) ? 类型:该单元中存放的数据长度类型,可能是字节 (Byte)、 字 (Word) 或双字 (Double Word)等,对应于类型值1、2、4
?标号——编程人员为目标地址单元起的名字,对应于该

指令在代码段中的存放地址。也有3种属性,仅类型与变量 不同:
? 类型:标号的类型共有远(Far)、近(Near)两种,类型值分 别是-2、-1

2 、 表达式与运算符
?

表达式——由运算符和操作数组成的、具有确定
结果的有意义的序列,可作为指令的操作数。
算符、分析运算符、合成运算符。

?

运算符——共有5类:算术运算符、逻辑运算符、关系运

?

操作数——常量、变量和标号等均可参与运算。对于地
址指针,只能进行加/减算术运算。

?

运算规则——表达式的值由汇编程序在编译的过程中自

动完成计算,所得确定的运算结果与操作码一起被编译成 机器码。

汇编语言的运算符
? ? ? ? ?

算术运算符:+、-、*、/、MOD、SHL、 SHR 逻辑运算符:AND、OR、XOR、NOT 关系运算符:EQ、NE、LT、GT、LE、 GE 分析运算符:SEG、OFFSET、TYPE、 SIZE、LENGTH 综合运算符:PTR、DS:、THIS、SHORT、 HIGH、LOW

算术运算符
? 数值表达式中可使用所有算术运算符 ? 地址表达式仅使用+、-算术运算符 ? 算术运算符不影响标志位

例:完成80H+90H
解:MOV AL,80H+90H;使用数值表达式 ;(AL)=10H、(CF)=不变 ? MOV AL,80H ADD AL,90H ;使用加法指令 ;(AL) =10H、(CF) = 1

算术运算符的使用
? 若以算术运算表达式作为源操作数,则整个表达 相当于立即数;运算结果(返回值)的长度由目 操作数决定
? 乘、除运算不带符号 ? 除法运算的返回值为整数商

? 表达式的运算不影响标志位 例:MOV AL,80H + 90H 相当于 MOV AL,10H 80H + 90H=10H由汇编程序完成; 指令执行后(AL)=10H,各标志位不变。

逻辑运算符
AND、OR、XOR、NOT ? 逻辑指令助记符与逻辑运算符形同意不同 ? 逻辑指令助记符出现在指令语句的开始 AND CX,00FFH AND 10AEH ? 逻辑运算符出现在指令语句的操作数段 AND CX,00FFH AND 10AEH 注:等价指令 AND CX,00AEH

逻辑运算符的使用
? 若以逻辑运算表达式作为源操作数,则整个表达 式相当于立即数;运算结果(返回值)的长度由 目操作数决定 ? 除NOT之外,均为双目运算符 ? 表达式的运算不影响标志位

例:AND CX,1F03H AND 72B6H 相当于 AND CX,1202H 1F03H ∧ 72B6H = 1202H由汇编程序完成, 各标志位不变;CX ∧ 1202H在执行过程中完成。

关系运算符
? EQ ? NE ? LT ? GT ? LE ? GE 相等关系 不等关系 小于关系 大于关系 小于等于关系 大于等于关系

进行关系判断时,表达式中所有 的数均视为无符号数

关系运算符
EQ、NE、LT、GT、LE、GE
? 两性质相同的操作数的比较

?若关系正确为真(T), 有全 1 操作数 ?若关系错误为假(F), 有全 0 操作数 例:MOV BL,(PORT LT 5)AND 20H ?若PORT=2,(PORT LT 5)=0FFH,为真 原式为 MOV BL,20H ?若PORT=7,(PORT LT 5)=00H,为假 原式为 MOV BL,00H

关系运算符的使用
? 关系运算的返回值 若关系成立,即为真,返回全1(1个字) 若关系不成立,即为假,返回全0 (1个字)
? 例:MOV BX ,(PORT LT 5)AND 20H 若 PORT = 2,(PORT LT 5)= 0FFFFH,为真 原式相当于 MOV BX,0020H 若 PORT = 7,(PORT LT 5)= 0000H,为假 原式相当于 MOV BX,0000H

分析运算符
?

分析运算符(数值返回运算符)的功能 符号地址段值属性返回符 符号地址偏移量值属性返回符 符号地址中数据类型属性返回符 DUP重复次数返回符 变量总字节数返回符

? SEG ? OFFSET ? TYPE ? LENGTH ? SIZE

分析运算符
? SEG
? OFFSET ? TYPE ? LENGTH ? SIZE

取变量/标号的段基值
取变量/标号的段内偏移量 取变量/标号的类型值 取以DUP定义的变量的重复次数 取以DUP定义的变量的总字节数

综合运算符
综合运算符(属性修改运算符)
? PTR ? THIS ? SHORT ? HIGH ? LOW ? ES:[ ] 存储器操作数重新定义类型运算符 存储器操作数重新定义类型运算符 页内跳转运算符 字数据中高字节数据分离符 字数据中低字节数据分离符 段属性前缀符

PTR运算符
? PTR的使用
类型
?

PTR

变量、内存单元或标号

作用

给原有的操作数重新赋定类型。表达式结果返回一个与原 有操作数具有相同的段基址和偏移量、不同类型的新操作数, 但并不另分配新的存储单元!
?

可用的类型名称(保留字)
? ?

变量或内存单元——BYTE、WORD、DWORD 标号——NEAR、FAR

PTR运算符
?

PTR的应用特点(MUL、DIV指令中的应用)

? MUL BYTE PTR [BX] ;(AX)←(AL)* [BX] ⑻ ? MUL WORD PTR [BX] ;(DX)(AX)←(AX)* [BX] ⒃ ? DIV BYTE PTR [SI] ;(AL)←(AX)/ [SI] ⑻ ? DIV WORD PTR [SI] ;(AX)← (DX)(AX)/ [SI] ⒃

PTR运算符
?

PTR的应用特点(JMP 指令中的应用)
? 段内间接近转移 —— CS不变、IP变 存储器中的 16 位值为段内 IP 目的地址 JMP WORD PTR [BX] JMP WORD PTR [2000H] ? 段间间接远转移 —— CS变、IP变 存储器中的 32 位值为 CS:IP 目的地址 JMP DWORD PTR [BX] JMP DWORD PTR [2000H]

综合运算符
?

HIGH、LOW的应用
? HIGH —— 分离字的高 8 位字节 ? LOW —— 分离字的低 8 位字节 ? 应用 MOV AH,BX ;指令错,源、目的操作数 类型不匹配 MOV AH,HIGH BX ;(AH)=(BH) MOV AH,LOW BX ;(AH)=(BL)

运算符的优先级别
优先级别 运算符 ( ) LENGTH SIZE
同 一 优 先 级 的 运 算 ? 按 从 左 到 右 的 顺 序 进 行 ? 没 有 括 号 时 ? 按 优 先 级 别 进 行 运 算 ?






PTR THIS OFFSET SEG TYPE 段超越前缀 HIGH LOW * / MOD + - EQ NE GT GE LT LE NOT AND OR XOR SHORT

同 一 表 达 式 内 可 进 行 多 种 运 算

?

8086汇编语言运算符
算术运算符 +(加) -(减) *(乘) 逻辑运算符 关系运算符 AND(与) EQ(相等) OR(或) XOR(异或) LT(小于) 分析运算符 SEG(求段基址) 综合运算符 PTR

NE(不相等) OFFSET(求偏移量) 段属性前缀 TYPE(求变量类型) THIS

/(除)
SHL(左移)

NOT(非) GT(大于)

SIZE(求字节数)

SHORT

MOD(求余)

SHR(右移)

LE(小于或等 LENGTH(求变量长 HIGH 于) 度) LOW GE(大于或 等于)

5.2 伪操作命令
?

数据类型定义伪指令

?
? ? ? ?

段定义伪指令
段说明伪指令 过程定义伪指令 符号定义伪指令EQU及= 地址计数器伪指令$

?

地址对准器伪指令ORG

数据类型定义伪指令
? ? ? ? ?

DB (Define Byte)—— 变量为字节数据类型 (8位) DW (Define Word)—— 变量为字数据类型 (16位) DD (Define DWord)—— 变量为双字数据类型 (32位) DQ (Define QWord) —— 变量为4字数据类型 (64位) DT (Define Tbyte) —— 变量为10字节数据类 型(80位)

数据类型定义伪指令
操作数可以为: (1)数值表达式; (2)ASCⅡ码字符串; (3)地址表达式; (4)?(只保存内存空间,未定义初始值); (5)DUP 子句,其格式为: 重复次数 DUP (操作数,…,操作数),DUP子句可以嵌套。

变量定义伪指令的使用
? 使用
[变量名] 变量定义伪指令 初值(表) [变量名] 变量定义伪指令 ? ;为变量赋初值 ;保留空间

? 常量、表达式均可作为初值 ? DB的特殊用法
[变量名] DB 字符串 7C00H ? 3FH,66H,70H,TYPE DATA1 ‘H72b9 &!’

? 例:
DATA1 DW DATA2 DD DB DATA3 DB

DW、DD的特殊应用
? 已有字节变量的定义: AVR1 DB ?
?

可用DW为16位地址指针赋值: DWAVR DW OFFSET AVR1 字变量DWAVR的值为AVR1的16位段内偏移量

? 可用DD为32位地址指针赋值: DDAVR DD AVR1 双字变量DDAVR的值为AVR1的逻辑地址(32位)

数据类型定义伪指令
?

DB、DW 的应用特点
DATA ARE1 ARE2 ARE3 ARE4 DATA SEGMENT DB 20H,30H DW 2030H DB ‘A’,‘B’ DW ‘AB’ ENDS
ARE1 20H 30H 30H 20H ARE3 ARE4 41H 42H 42H 41H

ARE2

数据类型定义伪指令
?

DW、DD用于存储器地址分配

? DW分配 16 位地址 DWAVR DW OFFSET AVR1 ? 变量 DWAVR 的类型为 16 位 ? 变量 DWAVR 的值为变量 AVR1 的 16 位偏移地 址 ? DD分配 32 位地址 DDAVR DD AVR2 ? 变量 DDAVR 的类型为 32 位 ? 变量 DDAVR 的值为变量 AVR2 的 32 位目标地 址

变量复制语句DUP ( )
? DUP的使用
[变量名] 变量定义伪指令 复制次数 DUP(复制内容) ;保留20H个字空间 ;将连续3个双字单元清0

? 应用
VAR DW 20H DUP(?) XA DD 3 DUP(0)

XB

DB 2 DUP(0FFH , ? , 4 , ‘4’)
LENGTH VAR=20H LENGTH XA=3 LENGTH XB=2 SIZE VAR=40H SIZE XA=12 SIZE XB=8

TYPE VAR=2 TYPE XA=4 TYPE XB=1

数据类型定义伪指令
存储器地址分配的应用
设DATA的段首地址为2000H
DATA SEGMENT ORG 0004H AVR1 DW 2030H AVR2 DB 40H DWVR DW OFFSET AVR1 DDVR DD AVR2 DATA ENDS
AVR1 30H 0004H 20H AVR2 40H 0006H DWVR 04H 0007H 00H
DDVR 06H 0009H 00H 00H 20H

段定义伪指令SEGMENT、ENDS
用于对 DS、ES、SS、CS 段的定义

段名标识符 SEGMENT [定位类型][组合类型][‘类别’]

〈段内定义〉 段名标识符 ENDS

段定义的相关约定
定位类型:规定段的起始边界,有4种选择: ?PAGE:段起始地址的最低8位必须为0。 ?PARA:段起始地址的最低4位必须为0。 ?WORD:段起始地址的最低1位必须为0,即从偶地址开始。 ?BYTE:段起始地址为任意值,即从任何地址开始都行。 缺省类型为PARA。 组合类型:表示与其它段的关系,为连接程序提供信息,可 以有6种选择: ?NONE:本段与其它段逻辑上不发生关系,每段都有自己 的基地址(缺省选择)。 ?PUBLIC:连接程序首先将本段与其它同名同类别的段相 邻地连接在一起,然后为所有这些PUBLIC段指定一个共同 的段基址。连接的先后次序由连接命令指定。

段定义的相关约定
?STACK:与PUBLIC同样处理,但此段作为堆栈段,SS指 向第一个STACK段。 ?COMMON:本段与其它同名同类别段重叠,段基址与最后 定义的相同,长度为同名段中最大段的长度。 ?AT表达式:连接程序把本段装在表达式值所指定的段地址 (此方式不能指定代码段)。 ?MEMORY:同PUBLIC连接程序将本段定位在被连接在一 起的其它所有段之上。

类别:给各段的名字信息,连接程序将类别名相 同的段组成一个段组用它们共同的名字作为这个 段组的名字。类别必须用单引号括起来。
例:STACK SEGMENT PARA STACK ‘STACK’

段说明伪指令ASSUME
ASSUME 伪指令仅用在代码段首行 代码段名 SEGMENT [相关约定] ASSUME CS:段名,DS:段名,…

〈代码段内定义,指令集合〉 代码段名 ENDS
例:ASSUME DS:DATA,SS:STACK,CS:CODE

过程定义伪指令
PROC FAR 、ENDP —— 远过程定义伪指令 PROC NEAR、ENDP —— 近过程定义伪指令 过程名 PROC FAR(NEAR) 〈过程指令集合〉 RET 过程名 ENDP 注:过程定义必须在代码段内 PROC FAR 为定义远过程 PROC NEAR 为定义近过程

符号定义伪指令EQU 、=
?

格式

符号 EQU 表达式 符号 = 表达式 注:符号而非变量,故用EQU、= 定义的 符号不占用存储器单元 ? 特点 EQU 不能重复定义 = 可重复定义 ,如 X = X+1 功能:给表达式指定一个等价的符号名。

符号定义伪指令EQU 、=
说明:

(1)=后的表达式只能是常数,对于字符或 字符串,在汇编时按整数处理。 (2) EQU后的表达式可以是数值、字符串, 甚至可以是寄存器名、指令的助记符等。 (3) EQU不能重复定义,而“=”伪指令可 以重复定义,其作用域从定义点到重新定义 之前。

符号定义伪指令


DATA ARE1 ARE2 ARE3 DATA

SEGMENT DB 20H EQU 20H DW 4142H ENDS

ARE1 20H 0000H ARE3 42H 0001H 41H

注: EQU定义的是常量,故不占存储单元

地址计数器伪指令$
把它称为程序计数器。表示位置计数器的当前值,可 以在数值表达式中使用。在程序中,“$”出现在表达式里, 它的值为程序下一个所能分配的存储单元的偏移地址。 表示下一个地址变量的偏移地址值ARRAY 25 0000H 46 SORTD SEGMENT 3

ARRAY DB 25,46,3,75,5 COUNT EQU $ - ARRAY SORTD ENDS ? ARRAY的偏移地址值为0000H ? $ 的偏移地址值为0005H ? COUNT = 0005H – 0000H = 5

75 5

$

0005H

地址对准器伪指令ORG
ORG是起始位置设定伪指令,用来指出源程序或数据块

的起点。利用ORG伪指令可以改变位置计数器的值。

下一个地址变量的偏移地址值由 ORG确定

VAR1

2

0002H

DATA SEGMENT ORG 2 VAR1 DB 2,3,4 ORG $ + 3 VAR2 DW 1234H DATA ENDS

3 4

$ $ + 3 34H 0008H
VAR2

12H

汇编结束伪指令
? END的使用 END 第一条指令的标号或主过程名

? 作用:表示汇编到此结束 ? 位于源程序的最后一行。END之后的语句不 会被汇编程序翻译

程序开始伪指令(自学)
? 在源程序开始处可以用NAME或TITLE为模块取名字。
① NAME伪指令 格式:NAME 模块名

汇编程序将以给出的“模块名”作为模块的名字。
② TITLE伪指令 如果程序中没有NAME伪指令,则也可使用TITLE伪指令。

格式:TITLE 正文(TEXT)
? TITLE伪指令可指定每一页上打印的标题。同时,若程序中没 有NAME伪指令,则汇编程序将用TEXT中的前6个字符作为模 块名。TEXT最多可有60个字符。 若程序中既无NAME又无TITLE伪指令,则将用源程序名作为 模块名。所以NAME及TITLE伪指令并不是必要的,但一般常 使用TITLE,以便在列表文件中能打印出标题来。

?

对准伪指令(自学)
EVEN伪操作使下一个字节地址成为偶数。一个字 的地址最好从偶地址开始,所以对于字数组为保证其 从偶地址开始,可以在它前面用EVEN伪操作来达到 此目的。例如: DATA_SEG SEGMENT ┇ EVEN WORD_ARRAY DW 100 DUP(?) ┇ DATA_SEG ENDS

LABEL伪指令(自学)
格式:名称LABEL 格式中的类型有 BYTE 、 WORD、 DWORD 、结构名、 记录名、NEAR、FAR共 7 种。前 5 种是属于变量的类型, 后两种是属于标号的类型。

格式中的名称就是语句的名称,为一标识符,若后面的 类型是前 5 种之一,那么该名称就是变量名;当类型为后两 种时,该名称就是标号。我们已经知道,变量与标号除具有 类型属性外,还具有段和偏移地址的属性,名称的这两个属 性就是汇编程序汇编到该语句时语句所在的段和偏移地址。

LABEL伪指令(自学)
该伪指令的功能是定义某变量名或标号的类型的。它虽具

有段与偏移地址的属性,但它并不占内存单元。
BARRAY LABEL BYTE; AARRAY DW 100 DUP(?) 上 面 定 义 了 两 种 类 型 的 变 量 , BARRAY 为 字 节 类 型 , AARRAY为字类型, 它们的段和偏移地址属性完全相同,都 是下面保留的 100 个字空间的首地址。其目的是为了程序中可 以对这 100 个字空间作两种不同类型的操作。在这一点上, LABEL的作用与前面介绍的PTR操作符的作用相类似。

5.3 DOS系统功能调用和BIOS中断调用
在我们的程序中,总会有数据的输入和输出。实现数据

的输入与输出将涉及输入、输出设备的管理,而对输入、输
出设备管理的具体操作是十分繁琐的,好在系统为我们提供 了方便。实际上,无论是用户程序还是DOS系统本身,都离

不开输入、输出操作,PC DOS系统将输入、输出管理程序编
写成一系列子程序,不仅系统可以使用,用户也可以像调子 程序一样方便地使用它们。在IBM PC系统中,除了DOS系统 中有一组输入、输出子程序可供用户调用外,在系统的ROM 中也有一组输入、输出管理程序可供用户使用,这组程序通 常称为ROM BIOS(ROM Input/Output System)。

DOS功能调用
调用系统提供的子程序,通常称为系统功能调用。功能 调用的基本方法是采用一条软中断指令INT n。所谓软中断是 以指令的方式产生的中断,当 CPU 执行该指令时,就像响应 外部中断一样的方式转入中断处理程序,中断处理程序结束

后又返回到INT指令的下一条指令处。指令中的n为中断类型
号,不同的n将转入不同的中断处理程序。所以,系统所提供 的处理输入、输出的子程序是以中断处理程序的方式编写的。

关于中断和如何转向中断处理程序以及中断处理程序的结构,
将在第7章中详细介绍。本节将主要说明与基本输入、输出有 关的 DOS 系统功能调用的调用方式及其用途,目的是为程序 设计中实现输入、输出操作打下基础。

DOS功能调用
类型号 20H 22H 中断功能 程序结束 结束地址 类型号 21H 23H 中断功能 请求DOS功能调用 中止(Ctrl-Break) 处理 磁盘顺序读 程序结束且驻留内存 DOS内部保留 DOS内部保留

24H 关键性错误处理
26H 28H 2FH 磁盘顺序写

25H
27H

DOS内部使用 29~2EH DOS内部使用 30~3FH

DOS功能调用
DOS系统功能调用主要是由软中断指令INT 21H

实现的,这是一条功能极强的指令。当累加器 AH中
设置不同的值时,指令将完成不同的功能,我们称 AH中设置的内容为功能号。该指令的功能大体可分 为输入、输出设备管理、文件管理及目录管理三个方 面。这里,我们主要介绍输入、输出设备管理的功能

及调用方式,DOS功能调用的其余功能请参阅附录C。
下面给出AH中设置的值与其对应的功能关系。

带回显的字符输入,功能号01H
?功能:从标准输入设备(如键盘)输入一个字符, 并显示在标准输出设备(如CRT)上。如无字符输 入,则等待。 ?入口参数:无

?返回值: (AL) = 输入字符的ASCII码
例:MOV AH,01H INT 21H CMP AL,0DH … ;功能编号 ;调用 ;输入字符是回车符吗?

字符输出,功能号02H
? 功能:将一个字符( ASCII 码)输出到标准输出 设备(如CRT)上 ? 入口参数:(DL)=即将输出字符的ASCII码 ? 返回值:无 例:MOV DL,‘$’;欲输出一个“$”符号

MOV AH,02H
INT 21H

;功能编号
;调用

无回显的字符输入,功能号08H
? 功能:从标准输入设备输入一个字符,不显示在 标准输出设备上。若无输入,则等待。 ? 入口参数:无 ? 返回值:(AL)= 输入字符的ASCII码 MOV AH,08H ;功能编号

INT 21H

;调用

输出字符串,功能号09H
?功能:向标准输出设备输出以“$”为结束符的字符 串(“$”符不显示),串中不含控制符 ?入口参数:地址指针DS:DX,指向待输出的字符串 首址 ?返回值:无 例:STR DB ‘Today is Monday.$’;即将输出的字 符串 … LDS DX,STR ;DS:DX为指针 MOV AH,09H ;功能编号 INT 21H ;调用

取输入状态,功能号0BH ?功能:检查标准输入设备 (如键盘) 是否有 输入,结果体现在返回值上。 ?入口参数:无 ?返回值: (AL) = 00H;表示无任何输入
? (AL)= 0FFH ;表示有任意输入 ;功能编号 例:MOV AH,0BH

INT 21H JZ READY

;调用 ;有则转至READY处

CMP AL,0FFH ;有按键吗?

程序终止,功能号00H
? 功能:通知 DOS 程序结束,并释放所占的内存空 间。这是程序退出DOS的方法之一。

? 入口参数:无
? 返回值:无

例:MOV AH,00H
INT 21H

;功能编号
;调用

进程结束,功能号4CH
? 功能:返回DOS或结束进程,并回送一个返回值。 ? 入口参数:(AL) = 返回值

? 返回值:无
例:MOV AL,01H MOV AH,4CH INT 21H ;送返回值 ;功能编号 ;调用

置中断向量,编号25H
?功能:将某个系统固定的中断向量(即中断处理程 序的入口地址)设置为用户自己的中断处理程序的 入口地址。 ?入口参数:(AL) =将要设置的中断类型号 ? (DS∶DX) = 中断处理程序的段基址∶偏移量 ?返回值:无
例:START: ;溢出中断处理入口 … MOV DS,SEG START;以DS:DX指向用户的中断入口 MOV DX,OFFSET START MOV AL,4 ;置4号中断 MOV AH,25H ;功能编号 INT 21H ;调用

取中断向量,编号35H
?功能:取系统固定的中断向量,并存入寄存器保存。 ?入口参数:(AL) = 要取的中断类型号 ?返回值:(ES:BX) = 系统的中断向量 例:MOV AL,0;取0号(除数为0)中断向量

MOV AH,35H
INT 21H PUSH ES PUSH BX

;功能编号
;调用

;将取得的中断向量段值入栈 ;段内偏移量入栈

结束用户程序、返回DOS的方法
?利用功能调用4CH
? MOV AH,4CH ? INT 21H

?利用功能调用00H
? MOV AH,00H

? INT 21H

?调用20H号中断
? 中断类型号为 20H 的中断服务功能是程序结束,所以在 程序结束时加上指令 INT 20H 即可返回。

结束用户程序、返回DOS的方法
? 转移至0单元
? 源程序进行汇编时,汇编程序会自动在 程序段前缀的开始处放上一条 INT 20H 指令,因此在用户程序结束时只要用无 条件转移指令: JMP 0 即相当于执行了调用 20H 号中断,可以 返回 DOS 。此法实际上与前一种方式是 一样的。

BIOS功能调用
BIOS提供了访问主要I/O设备的服务程序。

详见附录B

5.4 汇编语言程序设计
5.4.1 概述 对于任何一个编程者来说都想编制出一个高质量 的标准化软件程序,而一个高质量的标准化软件程序

应具备以下特点:
1.程序具有模块化结构,清晰易读,易调试易维护。 2.能够正常运行,结果正确。

3.执行速度快。
4.占用内存空间小。

程序设计一般应按下述步骤进行(对于给定的课题进行程序设 计): 1.依据设计任务,抽象出描述问题的数学模型。 2.确定实现数学模型的算法或求解的具体步骤和方法。 3.绘制出程序流程框图。流程框图一般包含起始框、执行框、 判断框和终止框,如图所示。

起始框

终点框

执行框

判断框

判断框

4.分配存储空间及工作单元(包括寄存器)。确定数据段、堆 栈段、代码段及附加段在内存中的位置。 5.依据流程图编写程序 6.静态检查(检查指令是否合适,是否有语法和格式错误)。 7.上机调试。 8.程序运行,结果分析。

5.4.2 程序设计方法
程序设计是指为计算机编写的、能够接受并执

行的、且具有实际意义的语句序列。对于汇编语言
程序设计,了解指令系统、伪指令及宏指令是最基 本的要求,这些内容在前面都已进行了介绍。合理 地使用不同的指令进行汇编语言程序的编制仅仅是 一个基础,是编出高质量程序的一个方面。然而程

序设计的方法可体现出一个程序设计者的思路及运
用指令的水平。

程序设计是把解决实际问题的方法转化为程序。由于

实际问题有简单与复杂之分,因此程序设计就需要根据解 决问题的思路,运用一些基本的程序设计方法设计出解决 不同问题的程序来。在汇编程序设计过程中,首先对要解 决的问题的过程进行具体的描述,这也是编程的准备阶段, 对于较小的程序可以使用程序流程图。对于较大的程序可 以采用模块化程序设计方法。无论采用流程图还是模块化 的方法设计都要使用程序设计的基本程序结构来表现出来。 基本的程序结构包括顺序结构、分支结构、循环结构及子 程序结构。由于不同的问题可采用不同结构设计,因此需 要对各种结构形式有所了解,才能找到解决某一问题的最 佳程序结构形式。

1. 基本源程序结构:过程定义法
CODE SEGMENT ASSUME CS:CODE,DS : DATA START PROC FAR ; START为过程名 PUSH DS MOV AX ,0 PUSH AX MOV AX , DATA 由于该过程由 DOS 调用,属于段间调用,故类型属性为 MOV DS ,AX ;上述为固定写法 FAR,在过程执行完后,执行 RET时,系统执行INT 20H, 程序正文(指令集合) 正确返回DOS系统。为了使用过程编写程序,并能返回DOS, RET ;过程返回 在程序段开始处先将 DS值 (DOS下)进栈,然后0值进栈,在 START ENDP ;结束过程定义 过程执行完后,执行 RET 指令,将DS和0偏移地址弹出来CS CODE ENDS ;结束代码段 和IP中,指向存放 INT ;结束汇编 20H的内存单元,执行INT 20H,结 END START 果返回DOS系统。

2. 基本源程序结构:主程序定义法
CODE SEGMENT ASSUME CS:CODE,DS:DATA MAIN: MOV AX,DATA MOV DS,AX

程序正文(指令集合)
MOV AH,4CH INT 21H CODE ENDS END MAIN ; 21H号中断退出 ; 结束代码段 ;结束汇编

3. 基本程序设计
?

顺序程序设计
指令指针IP值线性增加

?

条件程序设计
IP值受标志位的影响而跳变

?

循环程序设计
IP值受计数器CX中的值不为零而循环

顺序程序设计
顺序结构是一种最简单的程序设计结构形式。采用这 种结构只能完成简单的任务程序设计。顺序结构在任何结 构的程序中都会出现,因此说它是基础。下面举一个顺序 结构的程序设计例子,要求完成表达式所规定的操作: Y=X1+X2+X3。首先分析程序设计方法: ① 表达式 Y=X1+X2+X3 的计算过程可采用顺序执行的 方法来完成: 首先读入数据X1、X2、X3;其次计算X1、X2、 X3的和;最后保存结果到指定变量Y中。

② 根据计算步骤编写汇编语言程序:利用伪指令确定 存储器的分配,将X1、X2、X3定义为字变量;按照汇编语 言源程序结构要求编写源程序。

程序如下:

顺序程序设计

PROGRAM DATA SEGMENT DATA1 DW X1, X2, X3, ? DATA ENDS CODE SEGMENT ASSUME CS:CODE, DS:DATA START: MOV AX, DATA MOV DS, AX LEA SI, DATA1 MOV AX, [SI] ADD AX, [SI+2] ADC AX, [SI+4] MOV [SI+6], AX HLT CODE ENDS END START

顺序程序设计
可以看出,上面的源程序是由数据段和代码 段两部分组成的。在数据段定义了 X1 、 X2、 X3 为 自变量,在运行时应填入具体数值。代码段确定 了各段与段寄存器的关系,并且以计算机的基本 操作指令按顺序执行的结构形式将计算机操作过 程进行描述,从而完成程序设计的最初阶段任务。 一个源程序的编写过程还说明不了程序的正确性, 必须经过上机调试,才能验证设计的程序是否符 合要求。

例 试编程对两个无符号二进制数的加法,结果放入SUM。 分析 这是一个多字节求和任务,此任务应从低字节开始求和 ,在进行高字节求和时应考虑低字节的进位位。所以,低字 节求和时可以用ADD指令,但高字节求和时应用ADC指令。 流程图如图所示。 开始
初始化 分别取加数与被加数的低字节 低字节位求和 分别取加数与被加数的高字节 高字节带进位求和 存放结果 结束

编写程序如下:

DATA AAl AA2 SUM DATA CODE

SEGMENT DB 0C7H,24H DB 0ACH,79H DW 2DUP(?) ENDS SEGMENT ASSUME CS:CODE,DS:DATA START:MOV AX,DATA MOV DS,AX LEA SI,AA1 LEA DI,AA2 MOV AL,[SI] MOV BL, [DI] ADD AL,BL INC SI INC DI MOV AH,[SI] MOV BH,[DI] ADC AH,BH LEA SI,SUM MOV [SI],AX HLT CODE ENDS END START

用查表法求Z=X3 ? 定义数据段

顺序程序设计
TABLE 0 1 8 27 64 125 216

DATA SEGMENT TABLE DB 0, 1, 8, 27, 64, 125, 216 XVAL DB 6 YVAL DB ? DATA ENDS

? 定义堆栈段 STACK SEGMENT DB 100 DUP ( ?) STACK ENDS 注:堆栈段一般不定义, 由汇编程序自动生成

? 定义代码段 CODE SEGMENT ASSUME CS:CODE, DS:DATA START PROC FAR PUSH DS ;标准写法 MOV AX, 0 PUSH AX MOV AX, DATA MOV DS, AX LEA BX, TABLE MOV AL, XVAL ;程序指令 XLAT MOV YVAL, AL RET START ENDP CODE ENDS ;标准写法 END START

顺序程序设计

条件程序设计(分支结构程序设计)
在解决某些实际问题时,解决问题的方法随着某些条件 的不同而不同,将这种在不同条件下处理过程的操作编写出 的程序称为分支程序。程序中所产生的分支是由条件转移指 令来完成的。汇编语言提供了多种条件转移指令,可以根据 使用不同的转移指令所产生的结果状态选择要转移的程序段, 对问题进行处理。采用分支结构设计的程序,结构清晰、 易于阅读及调试。
下面是一个采用分支结构设计的程序例子,要求从键盘 上输入字符,若为 A ~ Z ,则将其转换为对应的 ASCII 码并 显示;若为0,则结束输入。

首先使用程序流程图将解决问题的思路描述出来,如图所示。程序如下: CODE SEGMENT 开 始 ASSUME CS:CODE ABC1:MOV AH, 01H ; 置键盘输入并回显 键 盘 输 入 并 显 示 INT 21H CMP AL, 0 ; 输入字符与0 Y 输 入 为 零 ? JZ ABC2 ;为零结束 CMP AL,‘A’ ;判断是否小于大写字母A N JL ABC1 ;小于大写字母A Y 输 入 字 符 CMP AL,‘Z’ ;判断是否大于大写字母Z < A否 ? JG ABC1 ;大于大写字母Z N MOV DL, AL ; 将AL内容送DL, N 输 入 字 符 MOV AH, 02H < Z否 ? INT 21H ;将A~Z的字符从显示器输出 Y ABC2:MOV AH,4CH ;带返回码结束INT 21H 字 符 送 显 示 器 输出 INT 21H CODE ENDS 结 束 END ABC1

条件程序设计

条件程序设计
在汇编语言程序设计中,根据各种条件判断和 比较进行操作,满足条件去做一种操作,不满足条 件去做另一种操作。每一种操作程序称为一个分支 ,一次判断产生两个分支,只有一次判断的称为单 重分支程序。多次判断产生多个分支,称为多重分 支程序。单重分支程序结构框图如图所示。
N 条件? Y N 条件? Y 程序1 程序2 程序1 程序2

条件程序设计
?

实现表达式
1 ( X > 0) Y= 0 (X = 0)

X在-128 ~ +127之间

- 1 (X < 0)
?

波形图

Y
X

条件程序设计
?

流程图

数据段定义 DATA SEGMENT X DB ? Y DB ? DATA ENDS ? 代码段定义 CODE SEGMENT ASSUME CS:CODE,DS:DATA MAIN :MOV AX, DATA MOV DS, AX ; 标准写法 MOV AL, X CMP AL, 0 JGE BIGER ; X 大于等于 0 转 BIGER
?

条件程序设计

条件程序设计
MOV AL, 0FFH MOV Y, AL JMP NEXT BIGER: JZ EQUL MOV AL, 1 MOV Y, AL JMP NEXT EQUL: MOV Y, AL ; -1的补码为FFH ; Y = -1 ; X 等于 0 转 EQUL

;Y=1
;Y=0 ; 结束程序返回DOS ; 结束代码段 ; 结束汇编

NEXT: MOV AH, 4CH
INT 21H CODE ENDS END MAIN

循环程序设计
循环结构程序设计针对的是处理一些重复进行的过程的 操作。采用循环结构设计的程序,其长度缩短了,不仅节省 了内存,也使得程序的可读性大大提高。使用循环结构形式 设计程序时, 通常将循环程序划分三个部分: ① 循环的初始化部分:主要为循环所需的变量赋初值。 ② 循环体:程序所要完成的主要工作部分,这一部分的内 容是由所要处理的问题来确定的,这一部分的执行结果可能 影响到循环是否继续进行。 ③循环控制部分:这一部分主要是以条件表达式的结果作 为是否结束循环的条件。在事先知道了循环次数的情况下, 可采用循环计数控制循环的结束;在事先不知道循环次数的 情况下,多采用结果及给定特征作为条件来控制循环的结束。 下图 可以帮助我们很好地理解循环结构程序。

常用的循环程序结构有两种形式: DO_UNTIL(直到型循环结构)结
构形式和DO_WHILE(当型循环结构)结构形式,如图所示。DO_ UNTIL 形式结构是先执行循环体程序,然后再判循环控制条件是否满足。若满足则 再次执行循环体程序;否则退出循环。DO_WHILE结构形式是先判断循环 控制条件是否满足,满足则执行循环体程序;否则退出循环。这两种形式的 循环程序结构,可根据具体情况在编程时选择其中一种。一般循环次数有可 能为零时,选择DO_WHILE形式结构,否则选择DO_UNTIL结构形式。
初始化 循环体 循环体 循环控制 Y 循环条件成立? Y N 循环条件成立? N 循环控制 初始化

预 置 循 环 次 数 其 他 准 备 工 作

预 置 外 循 环 次 数 其 他 准 备 工 作

循环程序的设计有两种形式:

单重循环程序设计和多重循环程序
设计。单重循环是循环回路只有一 个,循环控制变量只有一个。多重 循环是循环回路有多个,外循环中 套有内循环,循环控制变量有多个 (循环嵌套)。 在多重循环程序设计中应注意: ①内循环体可以几个并列在外循环体

循 环 体

预 置 内 循 环 次 数 其 他 准 备 工 作

循 环 减 1计 数 循 环 体 N 结 果 为 0? Y 退 出 循 环 (a) N 内 循 环 减 1计 数

结 果 为 0? Y 外 循 环 减 1计 数

内,但内循环体之间不得交叉。
②多重循环中可从内循环体转移到外 循环体,但不允许外循环体直接转到

N

结 果 为 0? Y 退 出 循 环 (b )

内循环体中。
③所编程序不能形成死循环程序。

图 (a) 单循环结构; (b) 双循环结构

循环程序设计
下面举例说明这类指令的功能及应用。
要求将偏移地址为1000H开始存放的100个字节的数据传 送到偏移地址为1500H开始的连续内存区。假设它们的段地址 存放在DS中,段地址为2000H。 在编写程序之前要对解决的问题进行分析: ① 首先确定程序采用循环结构完成数据搬家操作。 ② 定义数据单元。 ③ 按顺序将源数据逐一搬家(该步骤要求修改源数据 地址、目的数据地址及搬家次数)。 ④ 搬家程序的控制是以变化的数据个数作为条件。

程序如下: MOV AX, 2000H MOV DS, AX MOV SI, 1000H MOV DI, 1500H MOV CX, 100 AGAIN: MOV AL, [SI] MOV [DI], AL INC SI INC DI DEC CX JNZ AGAIN HLT 根据循环程序的嵌套层数不同,可以将循环程序的结构 分成单循环、双循环和多重循环。

例:要求将内存中以AREAY1为首地址的100个字节 数据搬移到以AREAY2为首地址的内存中去。

DATA SEGMENT AREAY1 DB 100DUP(?) AREAY2 DB 100DUP(0) DATA ENDS CODE SEGMENT ASSUME CS:CODE, DS:DATA START: MOV AX,DATA MOV DS,AX

MOV SI, OFFSET AREAY1 MOV DI,OFFSET AREAY2 MOV CX, 100 AGAIN: MOV AL, [SI MOV [DI], AL INC SI INC DI DEC CX JNZ AGAIN MOV AH, 4CH INT 21H CODE ENDS END START

例 将100个字符的字符串从内存的BUFFER1搬移到内存的BUFFER2中去。 DATA1 SEGMENT BUFFER1 DB 100DUP(?) DATA1 ENDS DATA2 SEGMENT BUFFER2 DB 100(0) DATA2 ENDS CODE SEGMENT ASSUME CS:CODE, DS:DATA1, ES:DATA2 START: MOV AX, DATA1 MOV DS, AX MOV AX, DATA2 MOV ES, AX MOV SI, OFFSET BUFFER1 MOV DI, OFFFET BUFFER2 MOV CX, 100 CLD REP MOVSB MOV AH, 4CH INT 21H CODE ENDS END START

循环程序设计
计算 S
?

?

100

i

i ?1

和清0 → AX 计数初值100 →CX

流程图
(AX) = (AX) + (CX) (CX) = (CX) - 1

N

(CX) = 0

Y
SUM = (AX)

循环程序设计
?

数据段定义

DATA SEGMENT SUM DW ? DATA ENDS
?

代码段定义

CODE SEGMENT ASSUME CS: CODE,DS: DATA MAIN: MOV AX,DATA MOV DS,AX ; 主程序定义法 MOV AX AX , 0 ; 和清零 XOR AX ,

循环程序设计
MOV CX,100 AGAIN: ADD AX, CX ; 赋计数初值 ; 累加

DEC CX
JNZ AGAIN MOV SUM,AX

; 计数器减 1
; CX 不为零循环

MOV AH,4CH ; DOS 中断号送 AH INT 21H ; INT 21H 返回

CODE ENDS
END MAIN

; 结束代码段
; 结束汇编

例 试编写程序,完成把从MEM单元开始的100个16位无符号 数按从大到小的顺序排列。

分析 这是一个双重循环排序 问题。由于是无符号数的比较, 可以用比较指令CMP和条件 转移指令JNC来实现。首先用 第一个数与第二个数比较,如 果第一个数大于第二个数,则 使其位置保持不变,如果第一 个数小于第二个数,交换两个 数的位置,即将大数放低地址, 小数放高地址。这样完成第一 次排序工作。再通过第二重的 99次循环,即可实现100个无 符号数的大小排序。流程框图 如图所示。程序如下:

开始 将外循环数存入寄存器BL

将内循环数存入寄存器CL Y

高地址数>低地址数? N

交换高、低地址中的数

修改内循环次数 N

CL=0? Y 修改外循环次数

N

BL=0? Y 结束

DATA SEGMENT ;定义数据段 MEM DW 100 DUP(?) ;定义100个数 DATA ENDS ;数据段结束 CODE SEGMENT ;定义代码 ASSUME CS:CODE , DS:DATA ;确定段和段寄存器之间关系 START:MOV AX, DATA MOV DS, AX ;初始化寄存器DS LEA DI , MEM ;DI指向要排序数的首地址 MOV BL ,99 ;外循环只需99次即可 ;外循环从此开始 AA1:MOV SI , DI ;SI指向当前要比较的数 MOV CL ,BL ;设置内循环计数的循环次数 ;以下为内循环

AA2:MOV AX , [SI] ;取低地址数 ADD SI , 2 ;修改地址 CMP AX , [SI] ;低地址数与高地址数比较 JNC AA3 ;若大于则不交换 MOV DX , [SI] MOV [SI-2] ,DX ;否则,两数交换 MOV [SI] , AX ;小数存高地址 AA3:DEC CL ;内循数减1 JNZ AA2 ;循环是否结束,如果没有结束(CL≠0), 则继续 ;内循环结束

DEC BL

;外循数减1

JNZ AA1

;循环是否结束,如果没有结束
(BL≠0), 则继续

;外循环体结束 MOV AH, 4CH INT 21H CODE ENDS ;送功能号 ;执行返回DOS 中断指令 ;代码段结束

END START ;源程序结束 气泡排序也是一种常用的排序方法,它的规则是:表中相邻 两元素一一比较,并把大值元素向下交换,直至表尾(大值元素 落底),此时,称为一次冒泡(程序中一次大循环)。以后重复 冒泡排序,直至最小元素冒到表顶为止。

七段共阴LED数码管显示
a f g d
c 1 1 0 1 1 1 1 1 1 1

b c dp
d 1 0 1 1 0 1 1 0 1 0 e 1 0 1 0 0 0 1 0 1 0 f 1 0 0 0 1 1 1 0 1 1 g 0 0 1 1 1 1 1 0 1 1 dp s s s s s s s s s s

e
a 1 0 1 1 0 1 0 1 1 1 b 1 1 1 1 1 0 0 1 1 1

七段数码输出(共阴极)

0 1 2 3 4 5 6 7 8 9

七段共阴LED数码管显示
?

数据段定义
;待显示的数值,带小数点
;第一个数的显示端口地址

DATA SEGMENT

VAL DB ‘47.531’
DISP EQU 6000H

TAB DB 0FCH,60H,0DAH,0F2H,66H;0~4 DB 0B6H,03EH,0E0H,0FEH,0E6H;5~9 TAB1 DB 0FDH,61H,0DBH,0F3H,67H;0.~4. DB 0B7H,03FH,0E1H,0FFH,0E7H;5.~9. DATA ENDS

?

七段共阴LED数码管显示 堆栈段定义

STACK SEGMENT PARA STACK ‘STACK’ DW 80 DUP(?) STACK ENDS

?

代码段定义

CODE SEGMENT ‘CODE’ ASSUME CS:CDOE,SS:STACK,DS:DATA STAB:MOV AX,DATA MOV DS,AX ;标准写法 LEA SI, VAL ;SI指向测试结果首址 CLD ;(DF )= 0,自动增量 LODS BYTE PTR VAL ;取第一个数至AL中 AND AL,0FH ;转换成十进制数

七段共阴LED数码管显示
LEA BX,TAB ;表首址TAB XLAT TAB ;查表 MOV DX,DISP ;DX为显示端口地址 OUT DX,AL ;第一个端口 INC DX ;下一个端口地址 LODS BYTE PTR VAL ;取带小数点的第二个数 AND AL,0FH LEA BX,TAB1 ;指向TAB1 XLAT TAB1 OUT DX,AL ;至第二个端口 INC DX INC SI ;小数点已送显

七段共阴LED数码管显示
MOV CX,3 ;余下3个数未转换 LEA BX,TAB ;不带小数点 AGN:LODS BYTE PTR VAL AND AL,0FH XLAT TAB OUT DX,AL INC DX LOOP AGN MOV AH,4CH ;完毕,返回DOS INT 21H CODE ENDS END STAB




友情链接: year2525网 工作范文网 QS-ISP 138资料网 528200 工作范文网 baothai 表格模版