8086 汇编程序设计

145
8086 汇汇汇汇汇汇

description

8086 汇编程序设计. CS. ∑. ALU. DS. SS. ES. IP. 内部寄存器. 8086CPU 内部结构框图. 地址总线 20 位. 数据总线 16 位. 总线控制电路. 8086 总线 16 位数据总线. ALU 数据总线 16 位. 暂存器. 队列总线 8 位. EU 控制器. 标志寄存器. 指令执行单元 EU. 总线接口单元 BIU. 8086CPU 内部结构框图. 通用、指针及变址寄存器. 通用寄存器 指针及 变址寄存器. 隐含定义 缺省搭配. 段寄存器和指令指针寄存器. 段寄存器 - PowerPoint PPT Presentation

Transcript of 8086 汇编程序设计

Page 1: 8086  汇编程序设计

8086 汇编程序设计

Page 2: 8086  汇编程序设计

8086CPU 内部结构框图

暂存器ALU

标志寄存器EU控制器

总线控制电路ALU 数据总线16 位

队列总线8 位

地址总线20 位

数据总线16 位

8086 总线16 位数据总线

指令执行单元 EU 总线接口单元 BIU

8086CPU 内部结构框图

通用寄存器AX AH ALBX BH BLCX CH CLDX DH DL

SPBPDISI

内部寄存器IPESSSDSCS

1 2 3 4 5 6

Page 3: 8086  汇编程序设计

通用、指针及变址寄存器 • 通用寄存器

• 指针及 变址寄存器

15 8 7 0

AX AH AL 累加器BX BH BL 基址寄存器CX CH CL 计数寄存器DX DH DL 数据寄存器

15 0

SP 堆栈指针寄存器BP 基址寄存器SI 源变址寄存器DI 目的变址寄存器

隐含定义

缺省搭配

Page 4: 8086  汇编程序设计

段寄存器和指令指针寄存器 • 段寄存器

• 指令指针寄存器

15 0

CS 代码段寄存器DS 数据段寄存器SS 堆栈段寄存器ES 附加段寄存器

15 0

IP 指令在代码段中的偏移量

CS:IP 当前正指向的指令的地址逻辑地址 物理地址如 CS=2000H IP=003AH 则物理地址为 2003AH

Page 5: 8086  汇编程序设计

物理地址的形成• 四个段寄存器 CS DS SS ES

• 逻辑地址由段寄存器和段内偏移量寄存器组成

• 物理地址 = 段寄存器的值 x 16

+ 段内偏移量寄存器的值

Page 6: 8086  汇编程序设计

物理地址的形成(续)• 物理地址 = 段寄存器的值 x 16 + 段内偏移量寄存器的值

段 内 偏 移 量15 0

物 理 地 址20 0

0000段 基 址15 0

不同的段基址和段内偏移量可得到相同的物理地址,如:

1234:0005

1230:0045

1200:0345

Page 7: 8086  汇编程序设计

逻辑地址的来源• CS,IP 指向代码段• SS,SP 指向堆栈段 代码段

数据段堆栈段

CSIP

DSBX(SI,DI)SS

SP

DS,BX(SI,DI) 指向数据段 ES,DI( 串操作 ) 指向附加段

段寄存器与段内指针寄存器有缺省搭配

Page 8: 8086  汇编程序设计

标志寄存器

• 运算结果标志 CF PF AF ZF SF OF

• 系统状态标志 TF IF DF

15 0

PSW 指令在代码段中的偏移量

15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0

OF DF IF TF SF ZF AF PF CF

Page 9: 8086  汇编程序设计

运算结果标志• 运算结果标志 CF PF AF ZF SF OF

CF: 进位 / 借位标志CF=1 CY 有进位 / 借位CF=0 NC

PF: 奇偶标志PF=1 PE 运算结果中有偶数个 1PF=0 PO

AF: 辅助进位标志AF=1 AC 有辅助进位 / 借位AF=0 NA 常用于 BCD 码运算

字节:带符号数 -128 ~ 127 10000000 ~ 01111111 (二进制 ) 字:带符号数 -32768 ~ 32767

ZF 零标志ZF=1 ZR 运算结果为零ZF=0 NZ

SF 符号标志SF=1 NG 运算结果为负SF=0 PL

OF 溢出标志OF=1 OV 带符号数运算结果溢出OF=0 NV

Page 10: 8086  汇编程序设计

系统状态标志• 系统状态标志 TF IF DF

TF: 陷阱标志TF=1 使 CPU 每执行一步(一条指令)即产生一个内部中断TF=0 禁止跟踪

IF: 中断标志IF=1 允许 CPU 响应外部的可屏蔽中断( STI )IF=0 禁止中断 (CLI)

DF: 方向标志DF=1 串操作指令为自动减量 (STD)

DF=0 串操作指令为自动增量 (CLD)

在指令: LODSB [DS:SI] STOSB [ES:DI] . . . . . .

Page 11: 8086  汇编程序设计

汇编语言程序设计1 汇编语言的基本语法2 汇编语言程序设计

Page 12: 8086  汇编程序设计

1 汇编语言的基本语法• 汇编语言源程序的格式• 常量、标识符和表达式• 指示性语句 ( 伪指令 )

• 名字与变量• 指令性语句

Page 13: 8086  汇编程序设计

DATA SEGMENT AT 2000H

ARRAY DB a1 , a2 , a3 ,… a10 ;a1 ~ a10 为立即数COUNT EQU $ - ARRAY ; 10-0=10

SUM DW ? ; 值不定DATA ENDS

STACK SEGMENT PARA STACK ‘STACK’

STAK DB 10 DUP (?) ; 复制 10 个不定值TOP EQU LENGTH STAK ; Length 是取变量长度的操作符STACK ENDS ; Top=10. 见 P44

汇编语言源程序的格式

Page 14: 8086  汇编程序设计

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

START: MOV AX , DATA MOV DS , AX ; DSDATA 段基址 MOV AX , 0 ; AX0 MOV DI , OFFSET SUM ; DI11 MOV BX , OFFSET ARRAY ; BX0 MOV CX , COUNT ; COUNT10

LOP: ADD AL , [BX] ; ALarray[0] ADC AH , 0 ; 进位加到 AH, INC BX : 见 ( 汇编指令 P45) LOOP LOP ; 见 ( 汇编指令 P99) MOV [DI] , AX ; SUMarray[i] MOV AH , 4CH ; 4CH 号 DOS 功能调用 INT 21H ; 为结束程序 , 见 P62

CODE ENDS END START

Page 15: 8086  汇编程序设计

汇编语言源程序格式的特点是 :

1 . 分段结构2 . 语句行汇编语言程序的语句有两类:( 1 ) 指令性语句 : 机器指令的汇编形式 ( 2 ) 指示性语句 ( 伪指令 ) : 不是机器指令 , 用来告诉汇编程 序以什么方式去汇编和组织程序和数据 .

汇编语言源程序的格式

Page 16: 8086  汇编程序设计

( 1 ) 指令性语句 格式为: [ 标号 ] : 操作码 [ 操作数 ] [ ; 注释 ]

带方括号的为任选项,标号是指令的符号地址,操作码和操作数是用汇编语言指令表示的指令部分,注释是对该语句在本程序中的功能的说明。

汇编语言源程序的格式

Page 17: 8086  汇编程序设计

例: NEXT : MOV AL , [BX][SI] ; Load Byte AND AL , 0FH

1. 标号2. 指令助记符 3. 操作数 无操作数 LODSB单操作数 JMP GO_ON双操作数 AND AL , 0FH4. 注释 可有可无,有则增加源程序的可读性

汇编语言源程序的格式

Page 18: 8086  汇编程序设计

( 2 ) 指示性语句格式为:

[ 名字 / 变量 ] 命令 [ 参数 ] [ ;注释 ]

命令指示汇编程序进行某种汇编操作,参数是有关的数据,名字是段名、符号名等标识符,变量用变量名表示。

汇编语言源程序的格式

Page 19: 8086  汇编程序设计

汇编语言源程序的格式例: CR EQU 0DH ; Carriage Return

NUM DB 30H , 31H , 32HCODE ENDS

ORG 100H… …

Page 20: 8086  汇编程序设计

一、常量其值在程序中不能改变的量 ,

在汇编语言源程序中的常量有:数字常量、字符常量和符号常量

( 1 ) 数字常量可以是二进制数、八进制数、十进制数或十六进制数表示

( 2 ) 字符常量是用单引号‘ ’括起来的 ASCII 字符, 其值是该字符的 ASCII 代码值

常量、标识符和表达式

Page 21: 8086  汇编程序设计

( 3 ) 符号常量是用标识符定义的常量。例如,采用符号定义语句 PORTA EQU 80H ,则指令 MOV AL , PORTA

与指令 MOV AL , 80H 等价。

常量、标识符和表达式

Page 22: 8086  汇编程序设计

标号名、符号名都称为标识符 字符个数 1 ~ 31 首字符为字母;” ?” ;” @” ;” _” 其它字符为字母;” ?” ;” @” ;” _” 和数字 不能使用保留字

如: AX 、 MOV 、 CODE 、 ORG ……

常量、标识符和表达式

Page 23: 8086  汇编程序设计

表达式由操作数和运算符组成。 操作数可以是常量、名字、变量和标号等。

运算符包括算术运算符逻辑运算符关系运算符分析运算符合成运算符等。

常量、标识符和表达式

Page 24: 8086  汇编程序设计

优先级

1 括号中的项,即(…)和 […]2 LENGTH , SIZE , WIDTH , MASK3 PTR , OFFSET , SEG , TYPE , T

HIS4 × , / , MOD5 + , -6 EQ , NE , L , LE , GT , GE7 NOT8 AND9 OR , XOR

常量、标识符和表达式

Page 25: 8086  汇编程序设计

一 、程序开始和结束语句• NAME 命令:给程序模块命名

格式: NAME 名字• TITLE 命令:名字作为每页标题打印出来,标题名字符不大于 60 个 格式: TITLE 名字• END 命令:主模块结束必须写上标号

格式: END [ 标号 ]标号是程序中第一句指令性语句的标号。

指示性语句

Page 26: 8086  汇编程序设计

二、段定义语句 用来定义一个段• SEGMENT / ENDS 命令 格式 :段名 SEGMENT [ 参数 ]

…….

段名 ENDS

段名由程序员定义,汇编时由系统为该段分配一个段基值,并将该值赋于段名。

指示性语句

Page 27: 8086  汇编程序设计

SEGMENT 语句中的参数为:[ 定位类型 ] [ 组合类型 ] [ ‘ 类别 ’ ]

用来设定该段在内存中的位置和在汇编、连接时,当该段与其它段组合在一起时该段同其它段的连接关系。都是任选项

指示性语句

Page 28: 8086  汇编程序设计

指示性语句 段 名 伪指令 定位类型 组合类型 类别名

例: STACK1 SEGMENT PARA STACK ‘STACK’

DW 100HDUP(0)

STACK1 ENDS

• 段名:用户自选 • 定位类型

PAGE 256

PARA 16 缺省值WORD 2

BYTE 1

Page 29: 8086  汇编程序设计

指示性语句• 组合类型

NONE 与其它段无关,缺省选择PUBLIC 公开的,与其它 PUBLIC 类型的段邻接存放,

用同一个首址COMMON 与另一个 COMMON 类型的段重叠(覆盖),

长度以最长的为准STACK 与其它 STACK 类型的段连接,且对 SP 初始化

• 类别名 用‘ ‘表示,由用户设定

Page 30: 8086  汇编程序设计

• ORG 命令:偏移地址定位语句指定某一语句在段内的偏移地址

格式 : ORG exp

exp 为能计算出 16 位立即数的表达式例:ORG 2000H

ORG $ + 1000H

指示性语句

Page 31: 8086  汇编程序设计

• ASSUME 命令: ASSUME 命令紧跟在代码段的 SEGM

ENT 语句之后,用于指示下述程序中段寄存器同指定段名的对应关系

格式 : ASSUME CS :段名 1 , DS :段名 2 , SS :段名 3 , ES :段名 4

注意: ASSUME 语句仅指出段寄存器同段名的对应关系,并未对段寄存器赋值,在程序中未用到的段寄存器不必指示。

指示性语句

Page 32: 8086  汇编程序设计

例: DATA SEGMENT

BUF DB 100H DUP(0)DATA ENDSSTACK1 SEGMENTDW 80H DUP(0)STACK1 ENDSCODESEGMENTASSUME CS:CODE,DS:DATA,ES:DATA,SS:STACK1……CODEENDS

指示性语句

Page 33: 8086  汇编程序设计

三、过程定义语句应用 PROC /ENDP 命令定义过程 ( procedure ) ,

过程即子程序,是程序的一部分,程序中用 CALL 指令调用过程,过程结束用 RET 指令返回程序。

格式 : 过程名 PROC 类型 ……

过程名 ENDP

类型为 FAR / [NEAR]

指示性语句

Page 34: 8086  汇编程序设计

四、数据定义语句用来为数据分配内存单元。格式 : [ 变量 ] 命令 参数 1 ,参数 2 ,…… [ ;注释 ]变量是内存中一组数的名字,由程序员在编程时用标识符定义,变量可以作为内存操作数来使用。

指示性语句

Page 35: 8086  汇编程序设计

数据定义语句中的命令可以是:DB 定义字节数据 (8 位 )DW 定义字数据 (16 位 )DD 定义双字数据 (32 位 )DQ 定义 8 字节数据 (64 位 )DT 定义 10 字节数据 (80 位 )

指示性语句

Page 36: 8086  汇编程序设计

参数是相应内存单元中的数据,可以是:数字常量……用各种规定的数制表示;字符常量……用单引号括起来的 ASCII 字符;符号常量……用 EQU 语句定义。

指示性语句

Page 37: 8086  汇编程序设计

? 保留一个存储单位,以备程序执行过程中存入结果数据;

? ? ? ? 保留 4 个存储单位;ARY DB 4 DUP ( 43H )

表示定义一个变量 ARY ,在内存中开辟一个数组 ,存放 4 个 43H 。

DUP 为复制符格式 :复制次数 DUP ( 数据 )

指示性语句

Page 38: 8086  汇编程序设计

例:DATA1 SEGMENT AT 2000H

ORG 3000H

ARY1 DB 12H , 34H , 56H , 78H

ARY2 DW 1234H , 5678H

ARY3 DB ‘A’ ,’ B’ ,’ C’ ,’ D’ , ,’ABCD’

ARY4 DW ‘AB’

ARY5 DD ‘AB’

ARY6 DW ARY2

ARY7 DD ARY2

Page 39: 8086  汇编程序设计

在定义 ARY6 的语句中,参数为已定义的变量 ARY2 ,其值为 ARY2 的偏移地址 3004H ;在定义 ARY7 的语句中,参数为已定义的变量 ARY2 ,其值为 ARY2 的偏移地址 3004H 和段基值 2000H 。

指示性语句

Page 40: 8086  汇编程序设计

五、符号定义语句• EQU 命令 等值命令

格式:名字 / 变量 EQU exp

• = 命令 等号命令格式 :名字 = exp

• PURGE 命令 用来撤消已定义的符号常量格式 : PURGE 名字可同时撤消几个己定义的名字

指示性语句

Page 41: 8086  汇编程序设计

六、名字与变量• 名字 名字包括文件名、标题名、段名、过程名和符

号常量名等,是程序员在编程中按标识符规定命名的,目的是方便编程和读程。

段名:在段定义语句中命名取定,定义后的段名可以作为段基值来使用,用来对段寄存器赋值,例如:

MOV AX , DATA1

MOV DS , AX

指示性语句

Page 42: 8086  汇编程序设计

过程名:在过程定义语句中定义,指向过程中第一条指令所在的内存单元的地址,即过程的入口地址,有 N

EAR(此过程仅被过程所在的段调用 ) 和 FAR (此过程被别的程序段调用 ) 之分。

符号常量名:由符号定义语句 EQU 、 = 来定义,对符号常量给以赋值。

指示性语句

Page 43: 8086  汇编程序设计

• 变量变量的定义和属性:变量由数据定义语句 DB/DW /DD/DQ/D

T 来定义。变量有三属性:段属性……说明该变量在哪个存储段中;偏移地址属性……说明该变量的段内偏移量;类型属性……说明该变量所在内存数据的类型(字节、字、双字、 8 字节还是 10 字节)。

指示性语句

Page 44: 8086  汇编程序设计

• 分析运算符 ( Analytic operator )

用于把变量的三个属性分别取出来作为操作数。 有 SEG 、 OFFSET. 、 TYPE 、 LENGTH 和 SIZE 。 SEG 变量名 ------ 取出变量的段基值 OFFSET 变量名 ------ 取出变量的偏移地址 TYPE 变量名 ------ 取出变量的类型值 . 字节数据、字数据、

双字数据、分别为 1 、 2 、 4 。 8 字节数据为 8 、 10 字节数据为 10 。

Page 45: 8086  汇编程序设计

LENGTH 变量名 : 表示变量所在数组的元素个数。 注意:只有当数据用 DUP 定义时,才适用,否 则恒为 1 。SIZE 变量名:表示变量所在数组的字节数。

注意: 同 LENGTH,

SIZE 变量 = LENGTH 变量 × TYPE 变量

指示性语句

Page 46: 8086  汇编程序设计

• 合成运算符PTR 运算符 类型 PTR exp

其中类型是BYTE 、 WORD 、 DWORD ( 变量 )

FAR 、 NEAR ( 标号 )

exp 为表达式 , 是存储器操作数,

指示性语句

Page 47: 8086  汇编程序设计

PTR 的应用• 用于临时改变变量或标号的类型属性。例如: BUFW DW 1234H , 5678H

MOV AX , BUFW

MOV AL , BYTE PTR BUFW

• 也可用来指定内存操作数的类型。 例如: INC BYTE PTR [ BX ]

INC WORD PTR [BX ]

指示性语句

Page 48: 8086  汇编程序设计

• 也可用 EQU 和 PTR 定义一个新的变量名例如: BUFW DW 1234H , 5678H

BUFB EQU BYTE PTR BUFW

则 MOV AX , BUFW 和 MOV AL , BUFB

都是合法的。

指示性语句

Page 49: 8086  汇编程序设计

THIS 类型 类似于 PTR 运算符,

THIS 与 EQU 一起用来定义一个新变量名。 例如 : BUFB EQU THIS BYTE

BUFW DW 1234H , 5678H

EQU 语句必须紧跟 DW 语句,并且 EQU 语句在前。

指示性语句

Page 50: 8086  汇编程序设计

LABEL 命令格式:变量 / 标号 LABEL 类型

用来定义语句中的变量 ( 或标号 )

例如: BUFB LABEL BYTE

BUFW DW 1234H , 5678H

LABEL 语句必须紧跟 DW 语句,并且 LABEL 语句在前。

指示性语句

Page 51: 8086  汇编程序设计

格式 : [ 标号 : ] 操作码 [ 操作数 ] [ ;注释 ]

• 标号 : 标号是一条指令在内存中的符号地址 标号有三属性

– 段属性:表示标号所在段的段基值;– 偏移地址属性:表示标号所在位置的偏移地址;– 类型属性:表示标号所在指令是允许段内跳转还

是段间跳转。

指令性语句

Page 52: 8086  汇编程序设计

– 用 PTR 重新指定标号类型设已定义标号 METER 为 NEAR 则段内转移用 JMP METER ; 段间转移用 JMP FAR PTR METER

– 用 EQU 和 PTR 定义新标号: METER :

KILOMT EQU FAR PTR METER

指令性语句

Page 53: 8086  汇编程序设计

– 用 EQU 和 THIS 定义新标号: KILOMT EQU THIS FAR METER :

– 用 LABEL 定义新标号:KILOMT LABEL FAR METER :

指令性语句

Page 54: 8086  汇编程序设计

• 操作数 : 操作数可以用段名、符号常量、变量、属性表达式、过程名和标号等。

例如:MOV AX , DATA ; DATA 是段名MOV CX , COUNT ; COUNT 是符号常量MOV BL , BUFFER ; BUFFER 是变量MOV SI , OFFSET ARRAY ; OFFSET ARRAY 是属

;性表达式CALL SBRT1 ; SBRT1 是过程名JMP DONE ; DONE 是标号

指令性语句

Page 55: 8086  汇编程序设计

2 汇编语言程序设计程序 ( PROGRAM ) 是完成特定功能的一组指令的

有序集合。程序设计的步骤是:

– 分析课题– 确定算法– 画流程图– 编写程序– 上机调试、修改

Page 56: 8086  汇编程序设计

2 汇编语言程序设计• 顺序程序• 分支程序 • 循环程序• 子程序• 系统功能调用

Page 57: 8086  汇编程序设计

– 指令顺序执行,无分支、无转移、无循环。–硬件支持是 IP 自动加 1 。 从内存取出一个指令字节, IP 自动加 1 。

顺序程序

Page 58: 8086  汇编程序设计

例 1. 查表求平方值DATA SEGMENTTABLESQ DB 0,1,4,9,16,25,36,49,

DB 64,81,100,121,144,169,196,225XX DB X ; X 为 0 ~ 15 的正整数YY DB ?DATA ENDSSTACK SEGMENT PARA STACK’STACK’

DB 50 DUP(?)STACK ENDS

Page 59: 8086  汇编程序设计

CODE SEGMENT ASSUME CS : CODE , DS : DATA ,

SS : STACKBEGIN : MOV AX , DATA

MOV DS , AX MOV BX , OFFSET TABLESQ MOV AH , 0 MOV AL , XX ADD BX , AX MOV AL , [BX] MOV YY , AL MOV AH , 4CH INT 21H

Page 60: 8086  汇编程序设计

注意:– 程序结束方法

1) 设计为一个 “过程” (PROCEDURE)

2) 以 MOV AH , 4CH; 终止当前程序并返回 INT 21H

即 4CH 号功能调用结束。– MOV AH , 0 ; AH 置 0 的必要性。– MOV , ADD 指令中 d 和 s 必需是相同类型。

Page 61: 8086  汇编程序设计

例 2 非压缩的 BCD 码转换为压缩的 BCD 码 MOV AX , DAT1 ; AX=0109

MOV CL , 4 ; CL=4

SAL AH , CL ; AH=10H

ROL AX , CL ; AX=0091

ROL AL , CL ; AL=19H

MOV BYTE PTR DATA , AL

DAT1 DW 0109H

Page 62: 8086  汇编程序设计

DOS为程序设计者提供了许多可用 INT 21H

指令直接调用的子程序。调用方法是:

(1)入口参数送指定的寄存器 , 如 DX;

(2)功能号 (即子程序编号 )送 AH;

(3)INT 21H指令有的调用可以不用第 1步。

系统功能调用

Page 63: 8086  汇编程序设计

01 号功能调用读取键盘字符并显示 – 调用方法: MOV AH , 01H

INT 21H

说明:扫描键盘,等待按键;若有键按下,检查按键码,当按下 CTRL-BREAK键时,则退出命令执行;当按下其它键时,则将对应的 ASCII 码送 AL 寄存器,同时送显示器显示。

系统功能调用

Page 64: 8086  汇编程序设计

• 02 号功能调用显示字符– 调用方法: 要输出显示的字符送 DL

MOV AH , 02H

INT 21H

说明:完成从标准输出设备显示器上显示一个字符。

系统功能调用

Page 65: 8086  汇编程序设计

例:利用 02 号功能调用完成输出显示一串字符信息。CODE1 SEGMENT

ASSUME CS: CODE , DS: CODE

ORG 100H

START : JMP BEGIN

MSG DB ‘This message was displayed with DOS

function 02H’

MSGLEN EQU $-MSG

BEGIN : MOV AX , CODE

MOV DS , AX

Page 66: 8086  汇编程序设计

MOV CX , MSGLEN MOV SI , 0 MOV AH , 02HNEXT : MOV DL , MSG[SI] INT 21H

INC SILOOP NEXTMOV AH , 4CHINT 21H

CODE ENDS END START

Page 67: 8086  汇编程序设计

A. 09 号功能调用字符串输出显示

– 调用方法:要输出显示的字符串的首地址送 DS :DX ;

MOV AH , 09H

INT 21H

说明 : 该功能调用完成在显示器上输出显示一字符串:字符串必须以字符‘ $’(24H) 为结束标志,但‘ $’ 字符不显示。

系统功能调用

Page 68: 8086  汇编程序设计

例 : 采用 09H 号功能调用 ,输出显示指定的字符串CODE SEGMENT ASSUME CS:CODE , DS: CODE ORG 100HSTART : JMP BEGINSTRING DB ‘Hello. How are you!’ ,’ $’BEGIN : MOV AX , CODE MOV DS , AX LEA DX , STRING MOV AH , 09H INT 21H MOV AH , 4CH INT 21HCODE ENDS END START

Page 69: 8086  汇编程序设计

系统功能调用• 40 号功能调用 — 显示器输出一串字符

—调用方法 :DS 指向显示串所在段DX 指向显示串串首CX 串长度BX 送 1MOV AH, 40HINT 21H

Page 70: 8086  汇编程序设计

• 0A号功能调用 — 字符串输入– 调用方法:从键盘接受字符的输入缓冲区首地址送DS: DX

说明:完成从键盘接收字符串存到指定内存的输入缓冲区,直到输入回车符为止。

缓冲区的第一个字节为指定缓冲区能接收的字符个数,第二个字节保留以用作填写实际输入字符的个数,第三个字节开始存放从键上输入的字符。

系统功能调用

Page 71: 8086  汇编程序设计

若实际输入的字符数少于定义的字节数,则缓冲区内其余字节补零;若实际输入多于定义的字节数,则多余字符丢弃,且响铃。例:利用 0AH 号功能调用,从键盘输入最多达 80 个字符的字符串存入以 BUF 为首址的缓冲区中。DATA SEGMENT

BUF DB 80

DB ?

DB 80 DUP (?)

DATA ENDS

系统功能调用

Page 72: 8086  汇编程序设计

CODE SEGMENT ASSUME CS: CODE , DS: CODESTART : MOV AX , DATA MOV DS , AX LEA DX , BUF MOV AH , 0AH INT 21H MOV AH , 4CH INT 21HCODE ENDS END START

Page 73: 8086  汇编程序设计

系统功能调用• 4C号功能调用 — 结束程序—调用方法 :MOV AX, 4CHINT 21H

Page 74: 8086  汇编程序设计

• 分支程序二要素具有判断和转移功能的程序。

– 判断:运算结果的状态标志 CF , PF , ZF , SF , OF ;– 转移:主要是条件转移指令 Jcc , cc 为条件。

单标志位判断…… JC , JZ , JO , JP , JS , JAE 等;多标志位判断…… JA , JG , JGE 等。

分子结构程序

Page 75: 8086  汇编程序设计

• 采用比较指令和转移指令实现分支CMP d , s ; d- s

Jcc 标号

分支结构程序

Page 76: 8086  汇编程序设计

例 3 符号函数处理有一符号函数 Y=f(X) 1 ; X > 0 Y= 0 ; X = 0 -1 ; X < 0

Page 77: 8086  汇编程序设计

MOV AL , XX

CMP AL , 0

JGE BIGR

MOV AL , 0FFH

MOV YY , AL ; X<0 时, -1送入 YY 单元HLT

BIGR : JE EQUL

例 3 符号函数处理

Page 78: 8086  汇编程序设计

MOV AL , 1

MOV YY , AL ; X>0 时, 1送入 YY 单元 HLT

EQUL : MOV YY , AL ; X = 0 时, 0送入 YY 单元 HLT

注意: JGE 是用于帶符号数的指令 MOV AL , 0FFH ; AL← -1

例 3 符号函数处理

Page 79: 8086  汇编程序设计

DATASEGMENTSTRG DB 1000 DUP (?)STG1 EQU STRG + 7STG2 EQU STRG + 25STRSE EQU 50DATA ENDSSTACK SEGMENT PARA STACK ‘STACK’STARN DB 100 DUP (?)STACK ENDS

例 4 数据块传送程序

Page 80: 8086  汇编程序设计

COSEG SEGMENT ASSUME CS : COSEG , DS : DATA , ES : DATA , SS : STACK

BEGIN MOV AX , DATA MOV DS , AX MOV ES , AX MOV CX , STRSE MOV SI , OFFSET STG1 MOV DI , OFFSET STG2

Page 81: 8086  汇编程序设计

CLD ;增量方式PUSH SIADD SI , STRSE-1CMP SI , DIPOP SIJB OKSTD ;减量方式传送

ADD DI , STRSE-1 ;指向数据块底部ADD SI , STRSE-1

Page 82: 8086  汇编程序设计

OK :REP MOVSB ;重复传送 50 个数据MOV AH , 4CH

INT 21H

COSEG ENDS

END BEGIN

变量为 STRG 、 STGl , STG2

符号常量为 STRSE

MOVSB 的功能为 [ DS : SI]B→ [ ES : DI]B

DS=ES=DATA

注意 CLD 和 STD 的作用。

Page 83: 8086  汇编程序设计

• 内存中连续存放的一系列跳转地址、跳转指令或关键字组成一个决定程序分支的跳转表。主要问题是计算表地址

表地址 = 表基地址 + 偏移量

利用跳转表实现分支

Page 84: 8086  汇编程序设计
Page 85: 8086  汇编程序设计

例 5 跳转表中存放跳转地址 DATA SEGMENT

BASE DW SBR0, SBR1, SBR2, SBR3DW SBR4, SBR5, SBR6, SBR7BN DB X ; X 为 0 ~ 7 之间的正整数DATA ENDSSTACK SEGEMNT PARA STACK ‘STACK’DB 100 DUP(?)

Page 86: 8086  汇编程序设计

COSEG SEGMENTASSUME CS:COSEG , DS:DATA ,

SS:STACKBEGIN MOV AX , DATA

MOV DS , AXMOV AL , BN

MOV AH , 0ADD AL , ALMOV BX , OFFSET BASE

Page 87: 8086  汇编程序设计

MOV BX , OFFSET BASEADD BX , AXMOV AX , [BX]JMP AXMOV AL , 4CHINT 21H

COSEG ENDS

END BEGIN

可用 JMP WORD PTR [BX] 替代 MOV AX ,[BX]JMP AX

Page 88: 8086  汇编程序设计

例 6 跳转表中存放跳转指令

Page 89: 8086  汇编程序设计

例 6 跳转表中存放跳转指令MOV AH , 0

MOV BL , AL

ADD AL , AL

ADD AL , BL

MOV BX , OFFSET BASE0

ADD BX , AX ;表地址计算 JMP BX

Page 90: 8086  汇编程序设计

例 7 计算 Y= ∑ai

DATA SEGMENT

TABLE DW a1, a2, …………………….., a10

DW a11, a21,……………………..a20

…….

DW a91,a92,…………………… a100

YY DW ?

DATA ENDS

循环程序

Page 91: 8086  汇编程序设计

程序一MOV AX , DATA 1

MOV DS , AX 2

MOV AX , 0 3

ADD AX , TABL 4

ADD AX , TABL+2 5

…………

ADD AX , TABL+198 103

MOV YY , AX 104

其中 ADD 指令有 l00条

Page 92: 8086  汇编程序设计

程序二:程序一中 4~103条指令可用如下 2 ~ 8条指令替代 MOV AX , 0 1

MOV BX , OFFSET TABL 2MOV CX , 100 3

LOP : ADD AX , [BX] 4INC BX 5INC BX 6DEC CX 7JNZ LOP 8MOV YY , AX 9MOV AH , 4CH 10INT 21H 11

Page 93: 8086  汇编程序设计

程序二为一循环结构程序 , 其中 :

指令 1~ 3 为初始化部分: 指令 4 为循环工作部分: 指令 5 , 6 为循环修改部分: 指令 7 , 8 为循环控制部分: 指令 9 为结束处理部分: 指令 10 , 11 为程序结束部分。 指令 4~8 三部分称为循环体,标号 LOP处称为循环头部。

Page 94: 8086  汇编程序设计
Page 95: 8086  汇编程序设计
Page 96: 8086  汇编程序设计

例 8 统计数组中负元素的个数数据块的定义如下:DATA SEGMENTD1 DB -1,-3,5,6,-9 ; 定义数组COUNT EQU $ -D1RS DW ? ; 存放负数个数DATA ENDS

Page 97: 8086  汇编程序设计

代码段程序为:CODE SEGMENT

ASSUME CS : CODE , DS : DATA

ASSUME SS : STACK

MOV AX , DATA

MOV DS , AX

MOV BX , OFFSET D1 ;建立数据指针 MOV CX , COUNT ;设置计数器初值

MOV DX , 0 ;设置结果初值

Page 98: 8086  汇编程序设计

LOP1: MOV AL , [BX]

CMP AL , 0

JGE JUS

INC DX

JUS: INC BX

DEC CX

JNZ LOP1 ;或 LOOP LOP1

MOV RS , DX

MOV AH , 4CH

INT 21H

例 7 和例 8 都是” 先执行,后判断 “的结构。

Page 99: 8086  汇编程序设计

例 9. 统计寄存器 AX 中 ” 1 ” 的个数。 MOV CX , 0

LOP : AND AX , AX

JZ STP

SAL AX , 1

JNC LOP

INC CX

JMP LOP

STP : HLT

这是一个“先判断后执行” 的结构。

Page 100: 8086  汇编程序设计

例 10. 软件延时程序SOFTDELAY PROC

MOV BL , 10

DELAY : MOV CX , 2801

WAIT : LOOP WAIT

DEC BL

JNZ DELAY

RET

SOFTDELAY ENDP

Page 101: 8086  汇编程序设计

这是一个二重循环程序, 内循环为: WAIT : LOOP WAIT

每个内循环可实现延时 l0ms ;外循环入口为 DELAY ,共进行 l0次 ,总延时 100ms 。

Page 102: 8086  汇编程序设计

• 子程序定义及结构– 主程序与子程序

子程序是一段相对独立的、能实现一定功能的、能被其它程序调用的程序段。能调用子程序的程序称为主程序。

– 调用与返回主程序用 CALL 指令调用子程序,子程序用 RET 指令返回主程序。

子程序

Page 103: 8086  汇编程序设计

• 子程序文件: 子程序说明与子程序。 – 子程序说明①功能描述:包括子程序名称、功能以及性能指标

( 如执行时间 ) 等;②所用寄存器和存储单元;③子程序的入口、出口参数;④子程序中又调用的其他子程序;⑤调用实例 ( 可无 ) 。

子程序

Page 104: 8086  汇编程序设计

– 子程序说明举例如下:;子程序 DTOB

;两位十进制数 (BCD 码 )转换成二进制数;入口参数: AL 中存放被转换数;出口参数: CL 中存放转换后的二进制数;所用寄存器: BX

;执行时间: 0.06ms

子程序

Page 105: 8086  汇编程序设计

– 子程序以过程名开始,以 RET 指令结束。例: DTOB PROC

RET

DTOB ENDP

子程序

Page 106: 8086  汇编程序设计

• 子程序应用中应注意的问题– 主程序与子程序的连接– 寄存器和工作单元中内容的保护,即保护现场,用 P

USH 指令和 POP 指令,可以安排在子程序中,也可以安排在主程序中。通常安排在子程序中。

– 参数的传递即主程序如何把入口参数带入子程序,子程序又如何把出口参数带回主程序。

子程序

Page 107: 8086  汇编程序设计

• 子程序嵌套与递归 子程序

Page 108: 8086  汇编程序设计

例 11 求数组之和主程序名为 MAIN, 子程序名为 SUM 。采用堆栈传递参数。程序如下:

STACK SEGMENT PARA STACK

SPAE DW 20 DUP(?)

TOP EQU LENGTH SPAE

STACK ENDS

DATA SEGMENT

ARY1 DB 100 DUP(?)

SUM1 DW ?

ARY2 DB 150 DUP(?)

SUM2 DW ?

DATA ENDS

Page 109: 8086  汇编程序设计

MAIN SEGMENT ASSUME CS: MAIN, DS: DATA, SS: STACK MOV AX , DATA MOV DS , AX MOV AX , SIZE ARY1 PUSH AX MOV AX , OFFSET ARY1 PUSH AX CALL SUM

…… MOV AX , SIZE ARY2

PUSH AX MOV AX , OFFSET ARY2

Page 110: 8086  汇编程序设计

PUSH AXCALL SUMHLTMAIN ENDSPROCE SEGMENTASSUME CS:PROCE, DS:DATA,SS:STACKSUM PROC FARPUSH AXPUSH BXPUSH CX

PUSH BPMOV BP , SPPUSHFMOV CX , [BP+14]

Page 111: 8086  汇编程序设计

MOV BX , [BP+12]MOV AX , 0

ADN: ADD AL , [BX]INC BXADC AH , 0LOOP ADNMOV [BX] , AXPOPF

POP BPPOP CXPOP BXPOP AXRET 4

SUM ENDS

Page 112: 8086  汇编程序设计

例 12. 求阶乘主程序名为 MAIN ,子程序有二个: FACT 为阶乘子程序,MULT 为字节数相乘子程序,实现 CL×DL=AX.

主程序:MAIN : MOV AX , 3 ;设 n = 3

CALL FACT

XI : MOV BX , DX

HLT

Page 113: 8086  汇编程序设计

FACT PROC ;阶乘子程序 FACTCMP AL , 0 ;入口参数: AL 中存放 nJNE IIAMOV DL , 1RETIIA : PUSH AXDEC ALCALL FACTX2 : POP CXCALL MULTX3 : MOV DX , AX ;出口参数: DX 中存放 n!RETFACT ENDP

Page 114: 8086  汇编程序设计

;无符号字节数乘法子程序 MULT;入口参数: CL 、 DL 中各为一乘数;出口参数: AX 中为乘积MULT PROC

…RET

MULT ENDP* 本例既有子程序嵌套,又有子程序递归。CALL FACT 是子程序递归,CALL MULT 是子程序嵌套。

Page 115: 8086  汇编程序设计

汇编语言程序举例例 1 :将 ASCII 码表示的两位十进制数转换成一字节二进制数 .

算法: 37H , 39H(ASCII 码 )→0000 , 0111B×10+0000 ,1001B→0100 , 1111BDATA SEGMENTASDEC DB 37H , 39HBIN DB ?DATA ENDSCODE SEGMENT ASSUME CS : CODE , DS : DATASTART : MOV AX , DATA

Page 116: 8086  汇编程序设计

MOV DS , AX

MOV SI , OFFSET ASDEC

MOV AL , [SI] ;取第一个数(十位数)SUB AL , 30H ;二进制数← ASC

SAL AL , 1 ;乘 10

MOV BL , AL

MOV CL , 2

SAL AL , CL

ADD BL , AL

INC SI

Page 117: 8086  汇编程序设计

MOV AL , [SI] ;取第二个数(个位数)

SUB AL , 30H ;二进制数← ASC

ADD AL , BL ;十位数 + 个位数 MOV BIN , AL ;存入 BIN

MOV AH , 4CH

INT 21H

CODE ENDS

END START

Page 118: 8086  汇编程序设计

例 2 :将 ASCII 码表示的两位 16 进制数转换成一字节二进制数。

算法: 41H , 36H (即‘ A’ ,‘ 6’ )→ 0AH , 06H→A0

H , 06H→A6H(1010 , 0110B)

DATA SEGMENT

ASHEX DB 41H , 36H

BIN DB ?

DATA ENDS

CODESEGMENT

ASSUME CS : CODE , DS : DATA

Page 119: 8086  汇编程序设计

START : MOV AX , DATA MOV DS , AX MOV SI , OFFSET ASHEX MOV AL , [SI] ;取第 1 个数 SUB AL , 30H ;转换成 16 进制数 CMP AL , 0AH JB NEXT1 SUB AL , 7NEXT1 : MOV CL , 4 ;左移 4 位 SAL AL , CL MOV BL , AL INC SI

Page 120: 8086  汇编程序设计

MOV AL , [SI] ;取第二个数 SUB AL , 30H ;转换成 16 进制数 CMP AL , 0AH JB NEXT2 SUB AL , 7NEXT2: OR AL , BL ;两个十六进制数组合 MOV BIN , AL ;存结果 MOV AH , 4CH INT 21HCODE ENDS END START

Page 121: 8086  汇编程序设计

例 3 :将一字节二进制数转换成两位 ASCII 码表示的十进制数。

算法:先将二进制数转换成十进制数,转换方法是从二进制数中减去 10 ,每够减 1次,就将结果的十位数加一。直到不够减为止,这时的十位数内容就是二进制数中 10 的个数,即十位数。最后一次的结果(差)为负,要加 10 以恢复原值,这就是个位数。然后将这两个数(十位数和个位数)转换成 ASCII 码。

Page 122: 8086  汇编程序设计

DATA SEGMENTBIN DB 01001111BASDEC DB 2 DUP (?)DATA ENDSCODE SEGMENT ASSUME CS : CODE , DS : DATASTART: MOV AX , DATA MOV DS , AX MOV DI , OFFSET ASDEC XOR AX , AX ; AH 和 AL 初值 =0 MOV AL , BINAGAIN: SUB AL , 10 JB NEXT

Page 123: 8086  汇编程序设计

INC AH ;够减,十位数加 1 JMP AGAINNEXT: ADD AL , 10 ;恢复个位数 ADD AH , 30H ;转换成 ASCII 码 MOV [DI] , AH INC DI ADD AL , 30H MOV [DI] , AL MOV AH , 4CH INT 21HCODE ENDS END START

Page 124: 8086  汇编程序设计

例 4 :将 ASCII 码表示的 5 位十进制数(注:不大于 65535 )转换成两字节二进制数。算法:设 5 位十进制数为 d4d3d2d1d0 ,其中 di 为十进制数字,这样表示的数,其值为:d4 ×104+d3×103+d2×102+d1×101+d0×100

=0×105+d4×104+d3×103+ d2×102+d1×101+d0×100

=[{[(0×10+d4)×10+d3]×10+d2}×10+d1]×10+d0

由此可见,可先设一个寄存器 AX 为 0 ,然后重复作乘以10+d 的运算,因为是 5 位数,故需重复做 5次(即循环 5次),就可得出结果。由于给出的是 ASCII 码,故需先将其转换成二进制数。

Page 125: 8086  汇编程序设计

DATA SEGMENTASDEC DB 33H , 39H , 36H , 32H , 35HCOUNT EQU $ - ASDECBIN DW ?DATA ENDSCODE SEGMENT ASSUME CS : CODE , DS : DATASTART: MOV AX , DATA MOV DS , AX MOV SI , OFFSET ASDEC MOV CX , COUNT XOR AX , AX;部分和 AX ,初值 =0AGAIN: ADD AX , AX ; AX×10 MOV BX , AX

Page 126: 8086  汇编程序设计

ADD AX , AX ADD AX , AX

ADD AX , BX MOV BH , 0 MOV BL , [SI] ;取 ASCII 码,转换成二进数 SUB BL , 30H ADD AX , BX ;部分和计算 INC SI ;修改地址指针 LOOP AGAIN MOV BIN , AX MOV AH , 4CH INT 21HCODE ENDS END START

Page 127: 8086  汇编程序设计

例 5 :将 16 位二进制数转换成用 ASCII 码表示的 5 位十 进制数。算法:本题算法与前面例 3 相同,只是例 3 的位数较少。具体是先从 16 位二进制数中减去 10000 ,够减的次数就是相应的万位数数字,由于最后不够减,故要加上 10000以恢复。然后依次用 1000 、 100 、 10 作减数,求得各位的数字。最后将它们转换成 ASCII 码。 DATA SEGMENTBIN DW 358CHASDEC DB 5 DUP ( ?)PWTAB DW 10000 , 1000 , 100 , 10 , 1DATA ENDS

Page 128: 8086  汇编程序设计

CODE SEGMENT ASSUME CS : CODE , DS : DATASTART: MOV AX , DATA MOV DS , AX MOV DI , OFFSET ASDEC MOV SI , OFFSET PWTAB MOV AX , BINLOP1: XOR CL , CL MOV BX , [SI]LOP2: SUB AX , BX JB NEXT INC CL JMP LOP2

Page 129: 8086  汇编程序设计

NEXT: ADD AX , BX ADD CL , 30H MOV [DI] , CL INC SI INC SI INC DI CMP BX , 1 JNZ LOP1 MOV AH , 4CH INT 21HCODE ENDS END START

Page 130: 8086  汇编程序设计

例 6 :编制完成两个 4 字节的 BCD 码( 8 位十进制数) 的加法运算程序。算法:将 4 字节的 BCD 码分为 4 个单字节数相加,从低字节开始,进行 4次循环操作,注意每次相加后必须进行 BCD修正。

DATA SEGMENTBCD1 DB 76H , 54H , 38H , 29HBCD2 DB 49H , 37H , 65H , 17HSUM DB 4 DUP (?)DATA ENDSCODE SEGMENT

ASSUME CS : CODE , DS : DATA

Page 131: 8086  汇编程序设计

MULBCDADD : MOV AX , DATA

MOV DS , AX

LEA SI , BCD1

LEA BX , BCD2

LEA DI , SUM

MOV CL , 4

CLC

AGAIN : MOV AL , [SI]

ADC AL , [BX]

DAA

Page 132: 8086  汇编程序设计

MOV [DI] , AL

INC SI

INC BX

INC DI

DEC CL

JNZ AGAIN

MOV AH , 4CH

INT 21H

CODE ENDS

END MULBCDADD

Page 133: 8086  汇编程序设计

例 7 :有一个 100 个字节的数据表,存放在数据段中,首地址为 TAB ,表内各数已按升序排列好。今给定一关键字,试编程从表内查找该关键字,若有,则结束;若无,将该关键字顺序插入表中,并修改表长(表长在 LTH 中)。算法:将给定关键字依次同数据表中的数据比较,若大于表中的数据,则继续同下一个数据比较,若小于表中数据,则先将从该数据开始的数据全部下移一个地址,然后将关键字插入表中空格,并将表长数加 1 。DATA SEGMENTLTH DB 100 ;表长TAB DB 0FH , 12H , 14H ,… ;数据表TEM DB 57H ;关键字DATA ENDSCODESEGMENTASSUME CS : CODE , DS : DATA , ES : DATA

Page 134: 8086  汇编程序设计

START : MOV AX , DATAMOV DS , AX

MOV ES , AX MOV BX , OFFSET TAB ; BX 指向数据表 MOV AL , TEM ;取给定关键字 MOV CL , LTH ;取表长 MOV CH , 00HLOP : CMP AL , [BX] ;在表中查找 JE SOP ;找到,结束 JL INST ;未找到,若给定关键字小于表;内元素,转 INST ,插入

INC BX LOOP LOP

Page 135: 8086  汇编程序设计

JMP JUST ;给定关键字一直大于表内元素, ;将关键字放在表末 INST : MOV DI , OFFSET TAB STD

ADD DI , LTH MOV SI , DI DEC SI REP MOVSBJUST : MOV [BX] , AL

INC LTHSOP : MOV AH , 4CH INT 21HCODE ENDS END START

Page 136: 8086  汇编程序设计

例 8 :有一数组含有 N 个数,要求用气泡排序法将其按升序排列。为便于分析,设该数组中仅有 10 个数,其值为:36 , -17 , 90 , -8 , -80 , -19 , 125 , -20 , 00 和 50 。算法:采用两两比较的方法,先拿第 N 个数 eN 与第 eN-1 个数比较,若 eN> eN-1 ,则不变动;反之,则交换。然后拿 eN-1 与 eN-2

相比,按同样方法决定是否交换,这样一直比较到 e2 与 e1比较。当第一次大循环结束时,数组中最小值冒到顶部。但数组尚未按大小排列好,还要进行第二次大循环,循环结束时,数组中第 2

小值也上升

Page 137: 8086  汇编程序设计

到顶部的相应位置…如果在一个大循环中,一次交换都未发生,或只在 eN 与 eN-1 相比较时发生过交换,则说明数组在此大循环中已经有序,这样下一次大循环就不再需要,因此可以设置一个交换标志,而把其初值设为 N (数组长度,即每次大循环中小循环变量 J 的初值)。未发生交换,标志不变;若发生交换,则把发生交换时的小循环变量 J

值赋予标志。在一个大循环结束时,检查标志,若其值为N (即一次交换都未发生,或仅在 eN 与 eN-1发生过一次交换),则停止排序。

Page 138: 8086  汇编程序设计

DATA SEGMENT BUFFERDW 36, -17 , 90 , -8 , -80 , -19 , 125 , -20 ,

00 , 50 COUNT EQU $ - BUFFER DATA ENDSCODE SEGMENT ASSUME CS : CODE , DS : DATASTART : MOV AX , DATA MOV DS , AX MOV DX , 2 ;大循环变量 ICONT1 : MOV CX , COUNT M

OV SI , CX

Page 139: 8086  汇编程序设计

DEC SI

DEC SI

SHR CX , 1 ;小循环变量 J

MOV BX , CX ;交换标志AGAIN : MOV AX , BUFFER[SI]

CMP AX , BUFFER[SI-2]

JGE NEXT

XCHG AX , BUFFER[SI-2]

MOV BUFFER[SI] , AX

MOV BX , CX ;置交换标志为 J

NEXT : DEC SI

DEC SI

Page 140: 8086  汇编程序设计

DEC CX

CMP CX , DX

JGE AGAIN

CMP BX , COUNT/2

JE DONE

INC DX

JMP CONT1

DONE : MOV AH , 4CH

INT 21H

CODE ENDS

END START

Page 141: 8086  汇编程序设计

例 9 :在已排好序的数据表中查找某个关键字,采用“对分查找法”。算法:设数据表中有 N 个数据升序排列,查找的关键字为“M” 。先取表中间值 eN/2 (即 N/2处的值),将 eN/2 与 M

比较,若 eN/2=M ,则已搜索到;若M> eN/2 ,则下一次取N/2 ~ N 之间的中间值 e3N/4 与 M比较;若M< eN/2 ,则下一次取 0 ~ N/2 之间的中间值 eN/4 与 M比较。这样,每查找一次,使区间缩小一半,一直进行下去,直到①被搜索的关键字已找到,或者②搜索区间变为 0 ,表示未搜索到。

Page 142: 8086  汇编程序设计

DATA SEGMENT

BUFFERDB‘A C D G I N R S T U V W X Y Z’

COUNT EQU $ - BUFFER

PTRN DW ?

CHAR EQU ‘M’

DATA ENDS

STACK1 SEGMENT PARA STACK ‘STACK’

STAPN DB 100 DUP (?)

STACK1 ENDS

CODE SEGMENT

ASSUME CS : CODE , DS : DATA

Page 143: 8086  汇编程序设计

START : MOV AX , DATA

MOV DS , AX

MOV SI , OFFSET BUFFER ;区间上限 L

MOV CX , COUNT

MOV DX , 1 ;查找次数初值 MOV AX , SI

ADD AX , CX

MOV DI , AX ;最后数加 1 为下限 R

MOV AL , CHAR

CONT1 : MOV BX , SI

ADD BX , DI

SHR BX , 1 ;中间序号 J= ( R+L ) /2

Page 144: 8086  汇编程序设计

CMP AL , [BX] ; eJ 与关键字比较 JZ FOUND

PUSHF

CMP BX , SI ; J= 上限吗? JZ NOFID; J= 上限,区间为 0 ,未找到 POPF

JL LESS ;关键字< eJ

MOV SI , BX ;关键字> eJ , J 作上限 L

JMP NEXT

LESS : MOV DI , BX ; J 作下限 R

NEXT : INC DX ;查找次数加 1

Page 145: 8086  汇编程序设计

JMP CONT1

NOFID : MOV DX , 0FFFFH ;未找到,标记 0FFFFH

POPF

FOUND : MOV AX , DX

MOV PTRN , AX ;结果送 PTRN

MOV AH , 4CH

INT 21H

CODE ENDS

END START