Upload
matia
View
131
Download
2
Embed Size (px)
DESCRIPTION
8086 汇编程序设计. CS. ∑. ALU. DS. SS. ES. IP. 内部寄存器. 8086CPU 内部结构框图. 地址总线 20 位. 数据总线 16 位. 总线控制电路. 8086 总线 16 位数据总线. ALU 数据总线 16 位. 暂存器. 队列总线 8 位. EU 控制器. 标志寄存器. 指令执行单元 EU. 总线接口单元 BIU. 8086CPU 内部结构框图. 通用、指针及变址寄存器. 通用寄存器 指针及 变址寄存器. 隐含定义 缺省搭配. 段寄存器和指令指针寄存器. 段寄存器 - PowerPoint PPT Presentation
Citation preview
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
∑
通用、指针及变址寄存器 • 通用寄存器
• 指针及 变址寄存器
15 8 7 0
AX AH AL 累加器BX BH BL 基址寄存器CX CH CL 计数寄存器DX DH DL 数据寄存器
15 0
SP 堆栈指针寄存器BP 基址寄存器SI 源变址寄存器DI 目的变址寄存器
隐含定义
缺省搭配
段寄存器和指令指针寄存器 • 段寄存器
• 指令指针寄存器
15 0
CS 代码段寄存器DS 数据段寄存器SS 堆栈段寄存器ES 附加段寄存器
15 0
IP 指令在代码段中的偏移量
CS:IP 当前正指向的指令的地址逻辑地址 物理地址如 CS=2000H IP=003AH 则物理地址为 2003AH
物理地址的形成• 四个段寄存器 CS DS SS ES
• 逻辑地址由段寄存器和段内偏移量寄存器组成
• 物理地址 = 段寄存器的值 x 16
+ 段内偏移量寄存器的值
物理地址的形成(续)• 物理地址 = 段寄存器的值 x 16 + 段内偏移量寄存器的值
段 内 偏 移 量15 0
物 理 地 址20 0
0000段 基 址15 0
不同的段基址和段内偏移量可得到相同的物理地址,如:
1234:0005
1230:0045
1200:0345
逻辑地址的来源• CS,IP 指向代码段• SS,SP 指向堆栈段 代码段
数据段堆栈段
CSIP
DSBX(SI,DI)SS
SP
DS,BX(SI,DI) 指向数据段 ES,DI( 串操作 ) 指向附加段
段寄存器与段内指针寄存器有缺省搭配
标志寄存器
• 运算结果标志 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
运算结果标志• 运算结果标志 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
系统状态标志• 系统状态标志 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] . . . . . .
汇编语言程序设计1 汇编语言的基本语法2 汇编语言程序设计
1 汇编语言的基本语法• 汇编语言源程序的格式• 常量、标识符和表达式• 指示性语句 ( 伪指令 )
• 名字与变量• 指令性语句
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
汇编语言源程序的格式
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
汇编语言源程序格式的特点是 :
1 . 分段结构2 . 语句行汇编语言程序的语句有两类:( 1 ) 指令性语句 : 机器指令的汇编形式 ( 2 ) 指示性语句 ( 伪指令 ) : 不是机器指令 , 用来告诉汇编程 序以什么方式去汇编和组织程序和数据 .
汇编语言源程序的格式
( 1 ) 指令性语句 格式为: [ 标号 ] : 操作码 [ 操作数 ] [ ; 注释 ]
带方括号的为任选项,标号是指令的符号地址,操作码和操作数是用汇编语言指令表示的指令部分,注释是对该语句在本程序中的功能的说明。
汇编语言源程序的格式
例: NEXT : MOV AL , [BX][SI] ; Load Byte AND AL , 0FH
1. 标号2. 指令助记符 3. 操作数 无操作数 LODSB单操作数 JMP GO_ON双操作数 AND AL , 0FH4. 注释 可有可无,有则增加源程序的可读性
汇编语言源程序的格式
( 2 ) 指示性语句格式为:
[ 名字 / 变量 ] 命令 [ 参数 ] [ ;注释 ]
命令指示汇编程序进行某种汇编操作,参数是有关的数据,名字是段名、符号名等标识符,变量用变量名表示。
汇编语言源程序的格式
汇编语言源程序的格式例: CR EQU 0DH ; Carriage Return
NUM DB 30H , 31H , 32HCODE ENDS
ORG 100H… …
一、常量其值在程序中不能改变的量 ,
在汇编语言源程序中的常量有:数字常量、字符常量和符号常量
( 1 ) 数字常量可以是二进制数、八进制数、十进制数或十六进制数表示
( 2 ) 字符常量是用单引号‘ ’括起来的 ASCII 字符, 其值是该字符的 ASCII 代码值
常量、标识符和表达式
( 3 ) 符号常量是用标识符定义的常量。例如,采用符号定义语句 PORTA EQU 80H ,则指令 MOV AL , PORTA
与指令 MOV AL , 80H 等价。
常量、标识符和表达式
标号名、符号名都称为标识符 字符个数 1 ~ 31 首字符为字母;” ?” ;” @” ;” _” 其它字符为字母;” ?” ;” @” ;” _” 和数字 不能使用保留字
如: AX 、 MOV 、 CODE 、 ORG ……
常量、标识符和表达式
表达式由操作数和运算符组成。 操作数可以是常量、名字、变量和标号等。
运算符包括算术运算符逻辑运算符关系运算符分析运算符合成运算符等。
常量、标识符和表达式
高
优先级
低
1 括号中的项,即(…)和 […]2 LENGTH , SIZE , WIDTH , MASK3 PTR , OFFSET , SEG , TYPE , T
HIS4 × , / , MOD5 + , -6 EQ , NE , L , LE , GT , GE7 NOT8 AND9 OR , XOR
常量、标识符和表达式
一 、程序开始和结束语句• NAME 命令:给程序模块命名
格式: NAME 名字• TITLE 命令:名字作为每页标题打印出来,标题名字符不大于 60 个 格式: TITLE 名字• END 命令:主模块结束必须写上标号
格式: END [ 标号 ]标号是程序中第一句指令性语句的标号。
指示性语句
二、段定义语句 用来定义一个段• SEGMENT / ENDS 命令 格式 :段名 SEGMENT [ 参数 ]
…….
段名 ENDS
段名由程序员定义,汇编时由系统为该段分配一个段基值,并将该值赋于段名。
指示性语句
SEGMENT 语句中的参数为:[ 定位类型 ] [ 组合类型 ] [ ‘ 类别 ’ ]
用来设定该段在内存中的位置和在汇编、连接时,当该段与其它段组合在一起时该段同其它段的连接关系。都是任选项
指示性语句
指示性语句 段 名 伪指令 定位类型 组合类型 类别名
例: STACK1 SEGMENT PARA STACK ‘STACK’
DW 100HDUP(0)
STACK1 ENDS
• 段名:用户自选 • 定位类型
PAGE 256
PARA 16 缺省值WORD 2
BYTE 1
指示性语句• 组合类型
NONE 与其它段无关,缺省选择PUBLIC 公开的,与其它 PUBLIC 类型的段邻接存放,
用同一个首址COMMON 与另一个 COMMON 类型的段重叠(覆盖),
长度以最长的为准STACK 与其它 STACK 类型的段连接,且对 SP 初始化
• 类别名 用‘ ‘表示,由用户设定
• ORG 命令:偏移地址定位语句指定某一语句在段内的偏移地址
格式 : ORG exp
exp 为能计算出 16 位立即数的表达式例:ORG 2000H
ORG $ + 1000H
指示性语句
• ASSUME 命令: ASSUME 命令紧跟在代码段的 SEGM
ENT 语句之后,用于指示下述程序中段寄存器同指定段名的对应关系
格式 : ASSUME CS :段名 1 , DS :段名 2 , SS :段名 3 , ES :段名 4
注意: ASSUME 语句仅指出段寄存器同段名的对应关系,并未对段寄存器赋值,在程序中未用到的段寄存器不必指示。
指示性语句
例: DATA SEGMENT
BUF DB 100H DUP(0)DATA ENDSSTACK1 SEGMENTDW 80H DUP(0)STACK1 ENDSCODESEGMENTASSUME CS:CODE,DS:DATA,ES:DATA,SS:STACK1……CODEENDS
指示性语句
三、过程定义语句应用 PROC /ENDP 命令定义过程 ( procedure ) ,
过程即子程序,是程序的一部分,程序中用 CALL 指令调用过程,过程结束用 RET 指令返回程序。
格式 : 过程名 PROC 类型 ……
过程名 ENDP
类型为 FAR / [NEAR]
指示性语句
四、数据定义语句用来为数据分配内存单元。格式 : [ 变量 ] 命令 参数 1 ,参数 2 ,…… [ ;注释 ]变量是内存中一组数的名字,由程序员在编程时用标识符定义,变量可以作为内存操作数来使用。
指示性语句
数据定义语句中的命令可以是:DB 定义字节数据 (8 位 )DW 定义字数据 (16 位 )DD 定义双字数据 (32 位 )DQ 定义 8 字节数据 (64 位 )DT 定义 10 字节数据 (80 位 )
指示性语句
参数是相应内存单元中的数据,可以是:数字常量……用各种规定的数制表示;字符常量……用单引号括起来的 ASCII 字符;符号常量……用 EQU 语句定义。
指示性语句
? 保留一个存储单位,以备程序执行过程中存入结果数据;
? ? ? ? 保留 4 个存储单位;ARY DB 4 DUP ( 43H )
表示定义一个变量 ARY ,在内存中开辟一个数组 ,存放 4 个 43H 。
DUP 为复制符格式 :复制次数 DUP ( 数据 )
指示性语句
例: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
在定义 ARY6 的语句中,参数为已定义的变量 ARY2 ,其值为 ARY2 的偏移地址 3004H ;在定义 ARY7 的语句中,参数为已定义的变量 ARY2 ,其值为 ARY2 的偏移地址 3004H 和段基值 2000H 。
指示性语句
五、符号定义语句• EQU 命令 等值命令
格式:名字 / 变量 EQU exp
• = 命令 等号命令格式 :名字 = exp
• PURGE 命令 用来撤消已定义的符号常量格式 : PURGE 名字可同时撤消几个己定义的名字
指示性语句
六、名字与变量• 名字 名字包括文件名、标题名、段名、过程名和符
号常量名等,是程序员在编程中按标识符规定命名的,目的是方便编程和读程。
段名:在段定义语句中命名取定,定义后的段名可以作为段基值来使用,用来对段寄存器赋值,例如:
MOV AX , DATA1
MOV DS , AX
指示性语句
过程名:在过程定义语句中定义,指向过程中第一条指令所在的内存单元的地址,即过程的入口地址,有 N
EAR(此过程仅被过程所在的段调用 ) 和 FAR (此过程被别的程序段调用 ) 之分。
符号常量名:由符号定义语句 EQU 、 = 来定义,对符号常量给以赋值。
指示性语句
• 变量变量的定义和属性:变量由数据定义语句 DB/DW /DD/DQ/D
T 来定义。变量有三属性:段属性……说明该变量在哪个存储段中;偏移地址属性……说明该变量的段内偏移量;类型属性……说明该变量所在内存数据的类型(字节、字、双字、 8 字节还是 10 字节)。
指示性语句
• 分析运算符 ( Analytic operator )
用于把变量的三个属性分别取出来作为操作数。 有 SEG 、 OFFSET. 、 TYPE 、 LENGTH 和 SIZE 。 SEG 变量名 ------ 取出变量的段基值 OFFSET 变量名 ------ 取出变量的偏移地址 TYPE 变量名 ------ 取出变量的类型值 . 字节数据、字数据、
双字数据、分别为 1 、 2 、 4 。 8 字节数据为 8 、 10 字节数据为 10 。
LENGTH 变量名 : 表示变量所在数组的元素个数。 注意:只有当数据用 DUP 定义时,才适用,否 则恒为 1 。SIZE 变量名:表示变量所在数组的字节数。
注意: 同 LENGTH,
SIZE 变量 = LENGTH 变量 × TYPE 变量
指示性语句
• 合成运算符PTR 运算符 类型 PTR exp
其中类型是BYTE 、 WORD 、 DWORD ( 变量 )
FAR 、 NEAR ( 标号 )
exp 为表达式 , 是存储器操作数,
指示性语句
PTR 的应用• 用于临时改变变量或标号的类型属性。例如: BUFW DW 1234H , 5678H
MOV AX , BUFW
MOV AL , BYTE PTR BUFW
• 也可用来指定内存操作数的类型。 例如: INC BYTE PTR [ BX ]
INC WORD PTR [BX ]
指示性语句
• 也可用 EQU 和 PTR 定义一个新的变量名例如: BUFW DW 1234H , 5678H
BUFB EQU BYTE PTR BUFW
则 MOV AX , BUFW 和 MOV AL , BUFB
都是合法的。
指示性语句
THIS 类型 类似于 PTR 运算符,
THIS 与 EQU 一起用来定义一个新变量名。 例如 : BUFB EQU THIS BYTE
BUFW DW 1234H , 5678H
EQU 语句必须紧跟 DW 语句,并且 EQU 语句在前。
指示性语句
LABEL 命令格式:变量 / 标号 LABEL 类型
用来定义语句中的变量 ( 或标号 )
例如: BUFB LABEL BYTE
BUFW DW 1234H , 5678H
LABEL 语句必须紧跟 DW 语句,并且 LABEL 语句在前。
指示性语句
格式 : [ 标号 : ] 操作码 [ 操作数 ] [ ;注释 ]
• 标号 : 标号是一条指令在内存中的符号地址 标号有三属性
– 段属性:表示标号所在段的段基值;– 偏移地址属性:表示标号所在位置的偏移地址;– 类型属性:表示标号所在指令是允许段内跳转还
是段间跳转。
指令性语句
– 用 PTR 重新指定标号类型设已定义标号 METER 为 NEAR 则段内转移用 JMP METER ; 段间转移用 JMP FAR PTR METER
– 用 EQU 和 PTR 定义新标号: METER :
KILOMT EQU FAR PTR METER
指令性语句
– 用 EQU 和 THIS 定义新标号: KILOMT EQU THIS FAR METER :
– 用 LABEL 定义新标号:KILOMT LABEL FAR METER :
指令性语句
• 操作数 : 操作数可以用段名、符号常量、变量、属性表达式、过程名和标号等。
例如:MOV AX , DATA ; DATA 是段名MOV CX , COUNT ; COUNT 是符号常量MOV BL , BUFFER ; BUFFER 是变量MOV SI , OFFSET ARRAY ; OFFSET ARRAY 是属
;性表达式CALL SBRT1 ; SBRT1 是过程名JMP DONE ; DONE 是标号
指令性语句
2 汇编语言程序设计程序 ( PROGRAM ) 是完成特定功能的一组指令的
有序集合。程序设计的步骤是:
– 分析课题– 确定算法– 画流程图– 编写程序– 上机调试、修改
2 汇编语言程序设计• 顺序程序• 分支程序 • 循环程序• 子程序• 系统功能调用
– 指令顺序执行,无分支、无转移、无循环。–硬件支持是 IP 自动加 1 。 从内存取出一个指令字节, IP 自动加 1 。
顺序程序
例 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
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
注意:– 程序结束方法
1) 设计为一个 “过程” (PROCEDURE)
2) 以 MOV AH , 4CH; 终止当前程序并返回 INT 21H
即 4CH 号功能调用结束。– MOV AH , 0 ; AH 置 0 的必要性。– MOV , ADD 指令中 d 和 s 必需是相同类型。
例 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
DOS为程序设计者提供了许多可用 INT 21H
指令直接调用的子程序。调用方法是:
(1)入口参数送指定的寄存器 , 如 DX;
(2)功能号 (即子程序编号 )送 AH;
(3)INT 21H指令有的调用可以不用第 1步。
系统功能调用
01 号功能调用读取键盘字符并显示 – 调用方法: MOV AH , 01H
INT 21H
说明:扫描键盘,等待按键;若有键按下,检查按键码,当按下 CTRL-BREAK键时,则退出命令执行;当按下其它键时,则将对应的 ASCII 码送 AL 寄存器,同时送显示器显示。
系统功能调用
• 02 号功能调用显示字符– 调用方法: 要输出显示的字符送 DL
MOV AH , 02H
INT 21H
说明:完成从标准输出设备显示器上显示一个字符。
系统功能调用
例:利用 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
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
A. 09 号功能调用字符串输出显示
– 调用方法:要输出显示的字符串的首地址送 DS :DX ;
MOV AH , 09H
INT 21H
说明 : 该功能调用完成在显示器上输出显示一字符串:字符串必须以字符‘ $’(24H) 为结束标志,但‘ $’ 字符不显示。
系统功能调用
例 : 采用 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
系统功能调用• 40 号功能调用 — 显示器输出一串字符
—调用方法 :DS 指向显示串所在段DX 指向显示串串首CX 串长度BX 送 1MOV AH, 40HINT 21H
• 0A号功能调用 — 字符串输入– 调用方法:从键盘接受字符的输入缓冲区首地址送DS: DX
说明:完成从键盘接收字符串存到指定内存的输入缓冲区,直到输入回车符为止。
缓冲区的第一个字节为指定缓冲区能接收的字符个数,第二个字节保留以用作填写实际输入字符的个数,第三个字节开始存放从键上输入的字符。
系统功能调用
若实际输入的字符数少于定义的字节数,则缓冲区内其余字节补零;若实际输入多于定义的字节数,则多余字符丢弃,且响铃。例:利用 0AH 号功能调用,从键盘输入最多达 80 个字符的字符串存入以 BUF 为首址的缓冲区中。DATA SEGMENT
BUF DB 80
DB ?
DB 80 DUP (?)
DATA ENDS
系统功能调用
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
系统功能调用• 4C号功能调用 — 结束程序—调用方法 :MOV AX, 4CHINT 21H
• 分支程序二要素具有判断和转移功能的程序。
– 判断:运算结果的状态标志 CF , PF , ZF , SF , OF ;– 转移:主要是条件转移指令 Jcc , cc 为条件。
单标志位判断…… JC , JZ , JO , JP , JS , JAE 等;多标志位判断…… JA , JG , JGE 等。
分子结构程序
• 采用比较指令和转移指令实现分支CMP d , s ; d- s
Jcc 标号
分支结构程序
例 3 符号函数处理有一符号函数 Y=f(X) 1 ; X > 0 Y= 0 ; X = 0 -1 ; X < 0
MOV AL , XX
CMP AL , 0
JGE BIGR
MOV AL , 0FFH
MOV YY , AL ; X<0 时, -1送入 YY 单元HLT
BIGR : JE EQUL
例 3 符号函数处理
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 符号函数处理
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 数据块传送程序
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
CLD ;增量方式PUSH SIADD SI , STRSE-1CMP SI , DIPOP SIJB OKSTD ;减量方式传送
ADD DI , STRSE-1 ;指向数据块底部ADD SI , STRSE-1
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 的作用。
• 内存中连续存放的一系列跳转地址、跳转指令或关键字组成一个决定程序分支的跳转表。主要问题是计算表地址
表地址 = 表基地址 + 偏移量
利用跳转表实现分支
例 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(?)
COSEG SEGMENTASSUME CS:COSEG , DS:DATA ,
SS:STACKBEGIN MOV AX , DATA
MOV DS , AXMOV AL , BN
MOV AH , 0ADD AL , ALMOV BX , OFFSET BASE
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
例 6 跳转表中存放跳转指令
例 6 跳转表中存放跳转指令MOV AH , 0
MOV BL , AL
ADD AL , AL
ADD AL , BL
MOV BX , OFFSET BASE0
ADD BX , AX ;表地址计算 JMP BX
例 7 计算 Y= ∑ai
DATA SEGMENT
TABLE DW a1, a2, …………………….., a10
DW a11, a21,……………………..a20
…….
DW a91,a92,…………………… a100
YY DW ?
DATA ENDS
循环程序
程序一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条
程序二:程序一中 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
程序二为一循环结构程序 , 其中 :
指令 1~ 3 为初始化部分: 指令 4 为循环工作部分: 指令 5 , 6 为循环修改部分: 指令 7 , 8 为循环控制部分: 指令 9 为结束处理部分: 指令 10 , 11 为程序结束部分。 指令 4~8 三部分称为循环体,标号 LOP处称为循环头部。
例 8 统计数组中负元素的个数数据块的定义如下:DATA SEGMENTD1 DB -1,-3,5,6,-9 ; 定义数组COUNT EQU $ -D1RS DW ? ; 存放负数个数DATA ENDS
代码段程序为: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 ;设置结果初值
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 都是” 先执行,后判断 “的结构。
例 9. 统计寄存器 AX 中 ” 1 ” 的个数。 MOV CX , 0
LOP : AND AX , AX
JZ STP
SAL AX , 1
JNC LOP
INC CX
JMP LOP
STP : HLT
这是一个“先判断后执行” 的结构。
例 10. 软件延时程序SOFTDELAY PROC
MOV BL , 10
DELAY : MOV CX , 2801
WAIT : LOOP WAIT
DEC BL
JNZ DELAY
RET
SOFTDELAY ENDP
这是一个二重循环程序, 内循环为: WAIT : LOOP WAIT
每个内循环可实现延时 l0ms ;外循环入口为 DELAY ,共进行 l0次 ,总延时 100ms 。
• 子程序定义及结构– 主程序与子程序
子程序是一段相对独立的、能实现一定功能的、能被其它程序调用的程序段。能调用子程序的程序称为主程序。
– 调用与返回主程序用 CALL 指令调用子程序,子程序用 RET 指令返回主程序。
子程序
• 子程序文件: 子程序说明与子程序。 – 子程序说明①功能描述:包括子程序名称、功能以及性能指标
( 如执行时间 ) 等;②所用寄存器和存储单元;③子程序的入口、出口参数;④子程序中又调用的其他子程序;⑤调用实例 ( 可无 ) 。
子程序
– 子程序说明举例如下:;子程序 DTOB
;两位十进制数 (BCD 码 )转换成二进制数;入口参数: AL 中存放被转换数;出口参数: CL 中存放转换后的二进制数;所用寄存器: BX
;执行时间: 0.06ms
子程序
– 子程序以过程名开始,以 RET 指令结束。例: DTOB PROC
RET
DTOB ENDP
子程序
• 子程序应用中应注意的问题– 主程序与子程序的连接– 寄存器和工作单元中内容的保护,即保护现场,用 P
USH 指令和 POP 指令,可以安排在子程序中,也可以安排在主程序中。通常安排在子程序中。
– 参数的传递即主程序如何把入口参数带入子程序,子程序又如何把出口参数带回主程序。
子程序
• 子程序嵌套与递归 子程序
例 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
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
PUSH AXCALL SUMHLTMAIN ENDSPROCE SEGMENTASSUME CS:PROCE, DS:DATA,SS:STACKSUM PROC FARPUSH AXPUSH BXPUSH CX
PUSH BPMOV BP , SPPUSHFMOV CX , [BP+14]
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
例 12. 求阶乘主程序名为 MAIN ,子程序有二个: FACT 为阶乘子程序,MULT 为字节数相乘子程序,实现 CL×DL=AX.
主程序:MAIN : MOV AX , 3 ;设 n = 3
CALL FACT
XI : MOV BX , DX
HLT
FACT PROC ;阶乘子程序 FACTCMP AL , 0 ;入口参数: AL 中存放 nJNE IIAMOV DL , 1RETIIA : PUSH AXDEC ALCALL FACTX2 : POP CXCALL MULTX3 : MOV DX , AX ;出口参数: DX 中存放 n!RETFACT ENDP
;无符号字节数乘法子程序 MULT;入口参数: CL 、 DL 中各为一乘数;出口参数: AX 中为乘积MULT PROC
…RET
MULT ENDP* 本例既有子程序嵌套,又有子程序递归。CALL FACT 是子程序递归,CALL MULT 是子程序嵌套。
汇编语言程序举例例 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
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
MOV AL , [SI] ;取第二个数(个位数)
SUB AL , 30H ;二进制数← ASC
ADD AL , BL ;十位数 + 个位数 MOV BIN , AL ;存入 BIN
MOV AH , 4CH
INT 21H
CODE ENDS
END START
例 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
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
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
例 3 :将一字节二进制数转换成两位 ASCII 码表示的十进制数。
算法:先将二进制数转换成十进制数,转换方法是从二进制数中减去 10 ,每够减 1次,就将结果的十位数加一。直到不够减为止,这时的十位数内容就是二进制数中 10 的个数,即十位数。最后一次的结果(差)为负,要加 10 以恢复原值,这就是个位数。然后将这两个数(十位数和个位数)转换成 ASCII 码。
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
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
例 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 码,故需先将其转换成二进制数。
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
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
例 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
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
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
例 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
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
MOV [DI] , AL
INC SI
INC BX
INC DI
DEC CL
JNZ AGAIN
MOV AH , 4CH
INT 21H
CODE ENDS
END MULBCDADD
例 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
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
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
例 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
小值也上升
到顶部的相应位置…如果在一个大循环中,一次交换都未发生,或只在 eN 与 eN-1 相比较时发生过交换,则说明数组在此大循环中已经有序,这样下一次大循环就不再需要,因此可以设置一个交换标志,而把其初值设为 N (数组长度,即每次大循环中小循环变量 J 的初值)。未发生交换,标志不变;若发生交换,则把发生交换时的小循环变量 J
值赋予标志。在一个大循环结束时,检查标志,若其值为N (即一次交换都未发生,或仅在 eN 与 eN-1发生过一次交换),则停止排序。
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
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
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
例 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 ,表示未搜索到。
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
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
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
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