版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
第4章汇编语言程序设计汇编语言的特点:利用汇编语言可以设计出效率较高的核心底层程序,如设备驱动程序;用汇编语言编写的程序一般比用高级语言编写的程序执行得快,且占内存较少;汇编语言程序能够直接有效地利用机器硬件资源,在一些实时控制系统中更是不可缺少和代替的;学习汇编语言是进行计算机应用系统设计的先决条件。汇编语言的应用70%以上的系统软件是用汇编语言编写的某些快速处理、位处理、访问硬件设备等高效程序是用汇编语言编写的某些高级绘图程序、视频游戏程序是用汇编语言编写的汇编语言是我们理解整个计算机系统的最佳起点和最有效途径主要内容:汇编语言源程序的结构汇编语言的语句与格式伪指令功能调用汇编语言程序设计4.1汇编语言源程序了解:计算机的三种语言源程序的结构汇编语言语句格式计算机设计语言机器语言汇编语言高级语言面向机器的语言机器语言汇编语言高级语言面向算法、过程或对象的语言汇编程序汇编语言源程序用助记符编写源程序的编译程序汇编程序汇编语言源程序机器语言目标程序汇编语言程序设计与执行过程输入汇编语言源程序源文件.ASM汇编(编译)目标文件.OBJ链接可执行文件.EXE调试最终程序汇编语言上机过程YYYNNN有错
?有错?有错
?结束汇编输入(修改)源程序连接运行查错开始用EDIT,NOTEPAD等任何文本编辑器。源程序存为.ASM文件用MASM宏汇编程序进行汇编。汇编后生成.OBJ目标文件。命令格式:MASM<源文件名.ASM>;用LINK连接程序进行连接。连接后生成.EXE可执行文件。命令格式:LINK<目标文件名.OBJ>;用TD、DEBUG等调试程序进行调试。命令格式:TD<可执行文件名.EXE>数据段名SEGMENT…数据段名ENDS附加段名SEGMENT…附加段名ENDS堆栈段名SEGMENT…堆栈段名ENDS代码段名SEGMENT…代码段名ENDSEND
4.1.1汇编语言源程序的结构
汇编语言的语句有两种:指令性语句——由8086指令助记符构成的语句指示性语句——由伪指令构成的语句指令性语句的格式为:[标号:]
[前缀]
指令助记符
[目的操作数,源操作数][;注释]指示性语句的格式为:[名字]
伪指令
[操作数1,操作数2,…,操作数n][;注释]
4.1.2汇编语言的语句与格式各部分之间至少要用一个空格作为分隔符指令性语句由CPU执行,每一条指令性语句都有一条机器码指令与其对应;
指示性语句由汇编程序执行。它指出汇编程序应如何对源程序进行汇编,如何定义变量、分配存储单元以及指示程序开始和结束等。指示性语句无机器码指令与其相对应。
指令性语句汇编时生成机器码;指示性语句汇编时不生成机器码。语句的构成元素:标号——指令的符号地址,用来代表指令在存储器中的地址。只能出现在指令性语句中,标号后应加上冒号。名字——段、过程、变量的名字,用来代表它们在存储器中的地址。只能出现在指示性语句中,名字后不加冒号。指令助记符——8086助记符、伪指令操作数——即指令的操作对象对指令性语句——0,1,2个对指示性语句——根据需要而定操作数之间以逗号分隔操作数可以是:寄存器、存储单元、常数或表达式
例如:AX,[DI+BX+10],200,16*8+TABLE,等等注释——以分号开头,可放在指令后,也可单独一行。
注意注解的写法。要写指令(段)在程序中的作用,而不要写指令的操作。
例如:以下为同一条指令写的注释
1)MOVCX,100;传送100到CX2)MOVCX,100;循环计数器置初值显然,第二种写法要比第一种写法要好。汇编语言的一个实例:hello.asm
dataSEGMENTHelloDB‘Hello,world!’,0DH,0AH,’$’dataENDSprogSEGMENTASSUME
CS:prog,DS:datastart:MOVAX,dataMOVDS,AX
LEADX,hello
;取字符串首地址
MOVAH,9INT21H ;显示字符串
MOVAH,4CHINT21H ;退回DOSprogENDSENDstart名字标号寄存器存储器单元常量变量或标号表达式4.1.3数据项与表达式常量数字常量字符串常量:用引号引起的字符或字符串例:‘A’,’ABCD’汇编时被译成对应的ASCII码41H,42H,43H,44H标号的属性:
段地址:即标号所在段的段地址;
偏移量:标号所代表存储单元的段内偏移地址;
类型:NEAR或FAR:
NEAR—表示标号所在语句与转移指令/
调用指令在同一码段内,跳转时只需改变IP即可。
FAR—标号所在语句与转移指令/调用指令不在同一代码段内。
若没有对类型进行说明,默认为NEAR。标号通常作为转移指令或CALL指令的转移地址。标号变量代表内存中的数据区,程序中视为存储器操作数变量的属性:段值变量所在段的段地址偏移量变量所在段的起始地址到变量地址之间的字节数类型字节型、字型和双字型变量在程序中作为存储器操作数被引用标号和变量名的使用规则组成:A-Z(不分大小写),0-9,?@._$不能以数字开头,圆点(.)只能作为首字符长度小于31个字符不能与保留字(指令助记符、伪指令、预定义符号等)重名不能重复定义例如:
正确的:LP1,AGAIN,NEXT,_GO,OK_1
错误的:4M,LOOP,AAA,#HELP,+ONE表达式表达式是常数、寄存器、标号、变量与运算符的组合。有数字表达式和地址表达式两种。汇编时按优先规则对表达式进行计算,计算出具体的数值或地址。运行时不能改变。表达式中的运算符有6类:算术、逻辑、关系、取地址、属性、其它类。算术运算符逻辑运算符关系运算符取值运算和属性运算符其它运算符用于数字表达式,例:
MOVAX,4*1024汇编后的形式为:MOVAX,4096用于地址表达式,例:LEASI,TAB+3若TAB的偏移地址为1000H,则汇编后的形式为:
LEASI,[1003H]算术运算符——+、-、*、/,MOD逻辑运算符只能用于数字表达式中。例:MOV CL,36HAND0FH
经汇编后:MOVCL,06H注意,不要把逻辑运算符与逻辑运算指令混淆:例:ANDAX,3FC0HAND0FF00H
汇编后源操作数被翻译为:3F00H,所以上述指令与ANDAX,3F00H等价。逻辑运算符——AND、OR、XOR、NOT关系运算的结果是一个逻辑值:真或假关系为真,结果为全1
关系为假,结果为全0例:MOVBX,PORTGT300H
若PORT的值大于300H,则汇编后为:
MOVBX,0FFFFH
否则汇编后为:
MOVBX,0关系运算符——EQ、NE、LT、GT、LE、GE取值运算符OFFSET取得其后变量或标号的偏移地址SEG取得其后变量或标号的段地址TYPE取变量的类型LENGTH取所定义存储区的长度SIZE取所定义存储区的字节数取值运算符例MOVAX,SEGDATAMOVDS,AXMOVBX,OFFSETDATA
LEABX,DATA等价于取值运算符例若BUFFER存储区是用如下伪指令定义:
BUFFERDW200DUP(0)
则:
TYPEBUFFER 等于2LENGTHBUFFER 等于200SIZEBUFFER 等于400属性运算符——PTR用来指定地址操作数的类型格式:<类型>PTR<地址操作数>
类型∈{BYTE,WORD,DWORD,NEAR,FAR}BYTE、WORD、DWORD
用于描述数据存储单元(变量)地址NEAR、FAR
用于描述转移、调用的目的地址例:MOV BYTEPTR[DI],0;字节类型
MOV WORDPTR[DI],0;字类型
MOV [DI],0B5H;类型不定PTR也可用来进行强制类型转换例:STR1DW? ;STR1定义为字类型
MOV AX,STR1;合法
MOV AL,STR1;非法
MOVAL,BYTEPTRSTR1;合法其它运算符方括号
[]方括号中内容为操作数的偏移地址段重设符:段寄存器名:[]用于修改默认的段基地址4.2伪指令由汇编程序执行的“指令系统”用于定义变量、分配存储区、定义逻辑段、指示程序开始和结束等常用伪指令数据定义伪指令符号定义伪指令段定义伪指令结束伪指令过程定义伪指令宏定义伪指令4.2.1数据定义伪指令用于定义数据区中变量的类型格式:[变量名]伪操作操作数[,…];注释某些情况下可省略可选伪指令助记符DB定义的变量为字节型DW定义的变量为字类型(双字节)DD定义的变量为双字型(4字节)DQ定义的变量为四字型(8字节)DT定义的变量为10字节型DATA1DB11H,22H,33H,44HDATA2DW11H,22H,3344HDATA3DD11H*2,22H,33445566H以上变量在内存中的存放形式伪指令的性质决定所定义变量的属性定义字符串必须用DB伪指令例:
DATA1DB‘ABCD’,66H‘A’‘B’‘C’‘D’41H42H43H44H66H重复操作符DUP为一个数据区的各单元设置相同的初值格式:
[变量名]伪指令助记符nDUP(初值,…)例:
DW20DUP(0)
DB3DUP(22H,11H,?)随机数用?预留存储空间MEM1DB34H,’A’,?,?,?MEM2DW20DUP(?)预留40个字节单元例:DATA_BDB10,5,10HDATA_WDW100H,-4DATA_DDD0FFFBH汇编后的内存分配情况如右图所示。05H10H00H01HFCHFFHFBHFFH00H00H0AHDATA_BDATA_WDATA_D10510H100H-40FFFBH例:操作数可以是字符串,例如
STRDB ‘HELLO’汇编后的情况如图:STR‘H’‘E’‘L’‘L’‘O’注意下面两个定义的不同之处:DB ‘AB’ ;41H在低字节,42H在高字节DW‘AB’;42H在低字节,41H在高字节48H45H4CH4CH4FH例:TABLEDB10DUP(?)BUFFERDWTABLE,$+3设TABLE的偏移地址为0080H,则汇编后如下图所示:BUFFER0080H80HTABLE008AH008BH008CH008DH...8FH00H00H0089H10Bytes4.2.2符号定义伪指令把一个表达式用一个符号表示,以后凡出现该表达式的地方都可用这个符号表示。符号定义伪指令有两种:EQU,=用EQU定义的符号未清除前,不能重新定义。清除EQU定义可用PURGE伪指令。用”=”定义的符号可在任何时候进行重定义。二者均不占用存储空间,仅是给符号赋值
例:FIVEEQU5
COUNTEQUCX
TENEQU10
DIST=BYTEPTR[SI+BP]GOTO=JMP…MOVAX,TENMOVCX,COUNTADDDIST,FIVEDIST=WORDPTR[SI+BP+1]ADDDIST,AX
GOTOLABEL定义引用4.2.3段定义伪指令说明逻辑段的起始和结束说明不同程序模块中同类逻辑段之间的联系形态汇编语言程序是按段来组织程序和数据的。和存储器的物理段相对应,汇编语言程序中的段称为逻辑段。汇编连接后被映射到物理段中。三类段:代码(程序)、数据、堆栈段定义伪指令:SEGMENT、ENDS、ASSUME、ORG定义一个段的基本格式:
段名
SEGMENT
[定位类型][组合方式][类别]<汇编语言语句>
段名
ENDS这两个伪指令总是成对出现,二者前面的段名应一致。SEGMENT说明了一个段的开始,ENDS说明了一个段的结束。对数据段和堆栈段,段中的语句一般是变量定义。对代码段则是指令语句。如:dataSEGMENT<指令语句>dataENDSSEGMENT和ENDS伪指令ASSUME伪指令在代码段中,还必须明确段和段寄存器的关系,这由ASSUME语句来指定。如
ASSUMECS:code,DS:data,ES:data
语句中的code和data为段名。这个语句说明:
1.CS将指向名字为code的代码段
2.DS和ES将指向名字为data的数据段但要注意,ASSUME伪指令只是告知汇编程序有关段寄存器与段的关系,并没有给段寄存器赋予实际的初值。故下面的语句
MOV AX,DATAMOV DS,AXMOV ES,AX将段基址装入段寄存器。如果程序中用到堆栈段,则SS也需装入实际的初值。代码段基地址不需要程序员装入CS寄存器,而由OS负责装入。SEGMENT语句后可以带有可选参数,用以规定逻辑段的其他一些属性。1)定位类型说明如何确定逻辑段的边界。有四种:PARA(Paragraph):
逻辑段从一个节(16个字节)的边界开始。即段的起始地址应能被16整除,或这说段起始物理地址应为××××0H。——默认类型BYTE:
逻辑段从字节边界开始,即段可以从任何地址开始。WORD:
逻辑段从字边界开始。即段的起始地址必须是偶数。PAGE:
逻辑段从页边界开始。256字节称为一页,故段的起始物理地址应为×××00H。
2)组合类型说明不同模块中同名段的组合方式。PUBLIC :
所有此类型的同名段组合成一个逻辑段,公用一个段地址,运行时装入同一个物理段中。COMMON:
所有此类型的同名段具有相同的起始地址(覆盖),共享相同的存储区域。AT<数值表达式>:按绝对地址定位,段地址就是表达式的值。STACK:专用于说明堆栈段,组合方式同PUBLIC3)类别用单引号括起来的字符串。所有同类别的段被安排在连续的存储区域中。如:在模块1中有段定义:
seg1SEGMENTPARASTACK‘stack’…seg1ENDS
在模块2中有段定义:
seg2SEGMENTPARASTACK‘stack’…seg2ENDS则连接时这两个段被安排在一起。位置计数器$表示当前位置的计数器汇编程序每扫描一个字节,位置计数器的值加1
如:TOPEQU$-STACKJMP$ORG规定了段内的指令或数据存放的开始地址(偏移地址的初值),其格式为:
ORG<表达式>表达式的值即为开始地址,从此地址起连续存放程序或数据。例:ABCSEGMENTORG100Hbegin:……ABCENDS定位伪指令ORG指令从100H开始存放4.2.4汇编结束伪指令END汇编语言源程序的最后,要加汇编结束伪指令END,以使汇编程序结束汇编。格式:END
[表达式]END后跟的表达式通常就是程序第一条指令的标号,指示程序的启动地址(要执行的第一条指令的地址)。4.2.5过程定义伪指令用于定义一个过程体格式:过程名PROC[NEAR/FAR]
┇
RET
过程名ENDP过程入口的符号地址过程的类型有两种:
NEAR——(默认类型)表示段内调用
FAR——表示段间调用
调用一个过程的格式为:
CALL
<过程名>4.2.6宏定义伪指令如果需要多次使用同一个程序段,可以将这个程序段定义为一个”宏指令”,然后在需要时,可简单地用宏指令名来代替这个程序段。指令的格式为:<宏指令名>MACRO
[形参表]<宏定义体>
ENDM例:两个数之和的宏定义和宏调用。宏定义为:DADDMACROX,Y,ZMOVAX,XADDAX,YMOVZ,AXENDMX、Y、Z是形式参数。调用宏DADD时可写为:
DADD
DATA1,DATA2,SUMDATA1,DATA2,SUM是实际参数,由它们替换定义中的X、Y、Z。宏调用与过程(子程序)调用都是一次定义,多次调用。它们之间的差别是:①执行形式:宏命令伪指令由宏汇编程序在汇编过理中进行处理,而CALL、RET则是由CPU执行的指令。②汇编结果:宏命令伪指令汇编后被展开。③执行速度:宏命令执行速度较快(因无调用转移)④
占用内存:宏指令简化了源程序,但不能简化目标程序,并不节省内存单元。使用过程可以节省代码占用的内存空间。宏展开:汇编程序会把宏调用按宏定义展开。例如:宏定义为:
DISPLAYMACROstringLEADX,stringMOVAH,9INT21H
ENDM
程序中宏调用:
……DISPLAYERROR_MESSAGEDISPLAYEXIT_MESSAGE……
汇编后的结果:(带有+号的指令为宏展开后的结果)……+LEADX,ERROR_MESSAGE+MOVAH,9+INT21H+LEADX,EXIT_MESSAGE+MOV AH,9+INT21H……一个完整源程序结构例DSEGSEGMENTDATA1DB1,2DATA2DW1234HDSEGENDSESEGSEGMENT
DB20DUP(?)ESEGENDSSSEGSEGMENT
STACK
‘STACK’
DB200DUP(?)SSEGENDSCSEGSEGMENT
ASSUMECS:CSEG,DS:DSEG,ES:ESEG,SS:SSEGSTART:MOVAX,DSEGMOVDS,AXMOVAX,ESEGMOVES,AXMOVAX,SSEGMOVSS,AX┇CSEGENDSENDSTART源程序代码段寄存器赋初值习题1.下列语句在存储器中分别为变量分配多少字节空间?并画出存储空间的分配图。VAR1 DB 10,2VAR2 DW 5DUP(?),0VAR3 DB ‘HOWAREYOU?’,‘$’VAR4 DD -1,1,02.假定VAR1和VAR2为字变量,LAB为标号,试指出下列指令的错误之处。(1)ADD VAR1,VAR2 (2)SUB AL,VAR1(3)JMP LAB[SI] (4)JNZ VAR13.对于下面的符号定义,指出下列指令的错误。
A1 DB ?
A2 DB 10 K1 EQU 1024
(1)MOV K1,AX
(2)MOV A1,AX
(3)CMP A1,A2
(4)K1 EQU 20484.3功能调用DOS功能调用高级调用,操作系统提供BIOS功能调用低级调用DOS功能调用包含多个子功能的功能包,用软中断指令调用,中断类型码固定为21H各子功能采用功能号来区分调用格式:
MOVAH,功能号
<置相应参数>INT21HDOS系统功能调用的使用方法如下:① AH←功能号;② 设置该功能所要求的其他入口参数;执行INT21H指令;分析出口参数。1.DOS键盘功能调用(1)从键盘输入一个字符(功能号=1)
MOVAH,1INT21H输入的字符在AL中功能:等待从键盘输入一个字符并将输入字符的ASCII码送入AL中,同时在显示器上显示该字符入口参数:无出口参数:AL=键入的ASCII码字符单字符输入例GET_KEY:MOV AH,1
INT 21H
CMP AL,’Y’ JZ YES CMP AL,’N’ JZ NO JNZ GET_KEY
YES:┇ NO:┇交互式应答程序(2)输入字符串(功能号=0AH)MOVAH,
0AH
LEADX,<字符串缓冲区首地址>INT21H功能:从键盘输入一串字符并把它存入用户指定的缓冲区中入口参数:DS:DX指向缓冲区首地址出口参数:输入的字符串及字符个数
DS:DX字符串在内存中的存放地址定义字符缓冲区用户自定义缓冲区格式:0DHN1N2整个缓冲区最大键入字符数实际键入字符数若用户键入的字符数(包括回车)≥定义的N1,本功能调用将不再接收新的键入,且光标不再向右移动。例:设在数据段定义键盘缓冲区如下:
STR1DB10,?,10DUP(?)
调用DOS功能的0AH号功能的程序段为:
LEADX,STR1MOVAH,0AHINT21H
此程序段最多从键盘接收10个按键(包括回车)。2.DOS显示功能调用(1)在显示器上显示一个字符(功能号=2)MOVAH,2MOVDL,<要显示的字符>INT21H
例:在显示器上显示一个字符‘A’MOVAH,2MOVDL,’A’;或MOVDL,41HINT21H
DL=待显示字符的ASCII码
MOVAH,9LEADX,<字符串>INT21H功能:在显示器上显示以‘$’(24H)为结束符的字符串,若显示的字符串要求回车换行,可在字符串中加入0DH,0AH控制码入口参数:DS:DX指向字符串首地址出口参数:无(2)显示字符串(功能号=9)被显示的字符串必须以‘$’结束例:在屏幕上显示:’HELLO,WORLD!’;在数据段定义字符串:
DATASEGMENTSTR1DB‘HELLO,WORLD!$’DATAENDS;在代码段中进行显示输出
MOVAH,9LEADX,STR1INT21H完整的程序:HELLO.ASM附:BIOS功能调用BIOS:基本输入输出系统,是固化在EPROM中的一组实现基本输入输出功能的子程序。BIOS调用通过多个软中断提供,调用方法为:
MOVAH,<功能号> <设置入口参数,一般将参数放在寄存器中> INT <中断类型>
BIOS中的几个主要中断类型如下:
INT10H——屏幕显示
INT13H——磁盘操作
INT14H——串行口操作
INT16H——键盘操作
INT17H——打印机操作 每类中断由包含许多子功能,调用时通过功能号指定。4.4汇编语言程序设计4.4.1概述1.程序质量(P170)2.汇编语言程序设计的步骤:
1-根据实际问题抽象出数学模型,确定算法
2-画出程序框图(流程图)3-分配内存工作单元和寄存器
4-根据框图编写源程序,存成.ASM文件
5-对源程序汇编,生成.OBJ目标文件
6-把.OBJ文件连接成.EXE执行文件
7-运行、调试3.源程序的基本结构:顺序、分支、循环、过程
(1)用方框表示工作框,框中用简明语言标明要完成的功能(2)用菱形框表示判断框
框中标明比较、判断和条件如何绘制程序框图(流程图)?NY?(4)各框之间用直线连起来表示程序走向。框中标明子程序名字(入口参数等)(3)用
框表示调用子程序或过程。4.4.2顺序程序设计顺序结构是最常见、最基本的程序结构CPU按照指令的排列顺序逐条执行。语句A语句B语句C程序的执行顺序就是指令的编写顺序例实现C=A+B,设A,B,C均为字变量。DATASEGMENTADW5F73HBDW98CDHCDW?DATAENDSCODESEGMENTASSUMECS:CODE,DS:DATASTART:MOVAX,DATAMOVDS,AXMOVAX,AADDAX,BMOVC,AXMOVAH,4CHINT21HCODEENDSENDSTART标号:条件满足?语句A4.4.3分支程序设计分支结构是指包含条件转移或无条件跳转指令的程序。分支结构具体分为单分支、双分支、多分支结构NYIF…THEN结构程序结构:
…
测试/比较指令(TEST/CMP)
条件转移指令(Jx
标号)
处理体
标号:其他指令
…单分支程序结构:
TEST/CMP指令
Jx
标号1
处理体P1JMP标号2标号1:
处理体P2标号2:其他指令
…条件满足?语句A语句B标号1:标号2:条件1条件2IF…THEN…ELSE结构双分支若条件成立,则执行A,否则执行B标号1:条件1成立?P1NYCASE结构程序结构:
…TEST/CMP指令(测试条件1)
Jx
标号1;不满足转标号1
处理体P1…JMP标号n+1标号1:TEST/CMP指令(测试条件2)
Jx
标号2;不满足转标号2
处理体P2…JMP标号n+1标号2:TEST/CMP指令(测试条件3)
Jx
标号3;不满足转标号3
处理体P3…JMP标号n+1标号3:TEST/CMP指令(测试条件4)
……标号n+1:(公共出口)条件2成立?条件n成立?…Pn+1标号2:标号n:标号n+1:P2PnNNYY例:将1字节的二进制数以十六进制数显示出来
DATASEGMENTADW5FHDATAENDSCODESEGMENT
ASSUMECS:CODE,DS:DATASTART:MOVAX,DATAMOVDS,AXMOVDL,AMOVCL,4SHRDL,CLADDDL,30H;0~9加30H,A~F加37HCMPDL,’9’JBENEXT1ADDDL,7NEXT1:MOV
AH,2
INT21H
MOVDL,AANDDL,0FHADDDL,30HCMPDL,’9’JBENEXT2ADDDL,7NEXT2:INT21HMOVAH,4CHINT21HCODEENDS
ENDSTART单分支程序设计例:在某串中查找某个特定字符,找到显示’Y’,未找到显示’N’
REPNESCASBJZFOUND
MOVDL,’N’JMPDISPFOUND:MOV
DL,’Y’DISP:MOVAH,2INT21H
MOVAH,4CHINT21HCODEENDS
ENDSTARTDATASEGMENTSTRINGDB‘Howareyou!welcometochina!’NEQU$-STRINGDATAENDSCODESEGMENT
ASSUMECS:CODE,ES:DATASTART:MOVAX,DATAMOVES,AXLEADI,STRINGMOVCX,NCLDMOVAH,1INT21H双分支程序设计4.4.4循环程序设计1.DO…UNTIL<条件>结构先执行,再判断条件。工作部分至少执行一次。初始化循环体循环控制继续循环?YN包含循环执行某一段指令序列的程序2.DOWHILE<条件>结构先判断条件,再执行。工作部分有可能一次都不执行。初始化循环体循环控制继续循环?YN循环结构的组成部分:循环初始化部分—初始化循环控制变量、循环体所用到变量;循环体部分—循环结构的主体,即要求重复执行得程序段部分,包括循环工作部分和循环控制部分;循环结束条件—在循环程序中必须给出循环结束条件,否则就会进入死循环。循环结束条件:用计数器控制循环按问题的条件控制循环用开关量控制循环有些情况下,在循环体内又嵌套了循环,这种结构成为多重循环。多重循环常用于软件延时程序或二维数组处理例:统计字变量VAL中0和1的个数,并将统计结果分别送字单元X和Y中。
MOVCX,16MOVSI,0MOVDI,0MOVAX,VALAGAIN:SHLAX,1JCNOZEROINCSIJMPNEXTNOZERO:INCDINEXT:LOOPAGAINMOVX,SIMOVY,DI掌握以下几点:调用子程序用CALL指令,返回调用程序用RET指令。子程序允许嵌套调用。进入子程序后首先要保护主程序的运行状态(标志位)和使用的寄存器内容(称为保护现场),退出子程序前要恢复现场。调用前要预先确定子程序中要使用哪些寄存器,并定义入口参数和出口参数。参数传递可利用寄存器、存储单元或堆栈(要用BP寻址)。4.4.5子程序设计对于一个子程序,应该注意它的入口参数和出口参数。入口参数—由主程序传给子程序的参数出口参数—子程序运算完传给主程序的结果参数传递的方法:利用寄存器。把所需传递的参数直接放在主程序的寄存器中传递给子程序。利用存储单元。主程序把参数放在公共存储单元,子程序则从公共存储单元取得参数。利用堆栈。主程序将参数压入堆栈,子程序运行时则从堆栈中取参数。例:编写一个将单字节的二进制数转换成BCD码数的程序,再将对应的十进制数转换成ASCII码字符串,在显示器上显示出来。分析:设单字节二进制数存放在NUMBIN单元。利用除法实现转换:将该数除以100,商即为BCD码数的百位,保留第一步所得余数。将①所得余数再除以10,商即为BCD码数的十位,余数即为BCD码数的个数将BCD码数的百位、十位和个位分别加上30H,即为它们的ASCII码将ASCII码字符串存入一个缓冲区,然后调用DOS功能调用INT21H的09H号功能即可显示该字符串。程序如下:DATASEGMENTNUMBINDB0E7H;待转换的单字节二进制数STRINGDB10DUP(20H);定义显示缓冲区,初值全为空格20HDB0DH,0AH;定义回车换行符
DB$;定义结束符DATAENDSSTACKSEGMENTPARASTACK‘STACK’DB100DUP(?)STACKENDSCODESEGMENTASSUMECS:CODE,DS:DATA,SS:STACKSTARTPROCFARBEGIN:PUSHDS;DS中包含的是程序段前缀的起始地址
MOVAX,0PUSHAX;设置返回至DOS的段值和偏移量
MOVAX,DATAMOVDS,AX;置段寄存器初值
LEADI,STRINGXORAH,AH;AH清零
MOVAL,NUMBINMOVBL,100DDIVBL;AX除以BL,商在AL中,余数在AH中
CALLBCDTOASC;调用转换程序,入口参数:AL=BCD数
MOVAL,AH;取余数送ALXORAH,AHMOVBL,10DDIVBL
CALLBCDTOASCMOVAL,AHCALLBCDTOASCCALLDISPASC;调用显示程序
RETSTARTENDPBCDTOASCPROC;BCD码到ASCII码转换程序
ADDAL,30HMOV[DI],AL;保存ASCII字符
INCDI;指向下一个单元
RETBCDTOASCENDPDISPASCPROC;显示子程序
LEADX,STRING
MOVAH,09HINT21HRETDISPASCENDPCODEENDSENDBEGIN1.码制转换十、二进制数、ASCII码之间的互相转换。①BCD数→二进制数算法:Dn-1*10n-1+……+D0*100
=(…(Dn-1*10+Dn-2)*10+…)*10+D0=(…((0*10+Dn-1)*10+Dn-2)*10+…)*10+D0
即:新的中间结果=中间结果*10+本位数字
(中间结果初值为0)4.5常见程序设计举例例:将≤65535的非压缩BCD数转换成二进制数。
;数据段定义
mydataSEGMENT
decnumDB5,3,0,1,9;BCD数53019
binnumDW?
mydataENDSprogSEGMENT
ASSUMECS:prog,DS:mydatabegin: MOVAX,mydata MOVDS,AX
MOVSI,OFFSETdecnum MOVCX,5;5位BCD数
MOVBX,10
XORAX,AX;中间结果初始值为0Next: MULBX;中间结果*10+本位数字
ADDAL,[SI]ADCAH,0
INCSI;指向下位BCD数
LOOPnextMOVbinnum,AX;保存结果
MOVAH,4CHINT21Hprog ENDS
ENDbegin例:把≤255的非压缩BCD数转换成2进制数
decnumDB1,5,9;BCD数159
binnumDB? ……MOVAX,decnumXCHGAH,AL;百位在AH,十位在ALAAD;百位数*10+十位数
MOVAH,AL;中间结果送AHMOVAL,decnum+2AAD;中间结果*10+个位数
MOVbinnum,AL……例:从键盘输入两个整数,并求其和。因键入为整数,故要进行如下转换:
ASCII→BCD→二进制数
ASCII→BCD码很简单,高4位清零即可得到非压缩的BCD码。
BCD→二进制数在本例中采用用以下方法:
((((0+千位数)*10+百位数)*10)+十位数)*10+个位数②ASCII码→二进制数(用于输入)第一次中间结果第二次中间结果第三次中间结果最终结果开始两个数分别转换成二进制数键入两个数相加结束返回DOS如有溢出则提示开始取第一个ASCII码是负号吗?数字符个数-1,指针+1指针定位字符个数-1=0?取数字,与中间结果相加,再乘以10指向下一个数字字符加个位数是负数则求补存结果结束NYYN转换子程序程序如下:DATA SEGMENTSTR1 DB10,?,10DUP(?);第1个数的输入缓冲区
STR2 DB10,?,10DUP(?);第2个数的输入缓冲区
NUM DW?,? ;存转换后的二进制数SUM DW0 ;存和OVER DB‘Overflow!’,13,10,’$’DATA ENDS;CODE SEGMENT ASSUMECS:CODE,DS:DATAMAIN PROC FARSTART:MOV AX,DATA MOV DS,AX MOV AH,0AH LEA DX,STR1 INT 21H ;输入第一个数字串(设为26) MOV AH,0AH LEA DX,STR2 INT 21H ;输入第二个数字串(设为33) LEA BX,STR1;串1的首地址送BX LEA DI,NUM;存二进制首地址送DI CALL CHANGE;将串1ASCII码→二进制
LEA BX,STR2;串2的首地址送BX
LEA DI,NUM+2 ;指向
CALL CHANGE ;将串2ASCII码→二进制
MOV AX,NUM;(AX)=[NUM]=001AH ADD AX,NUM+2 ;两数相加,(AX)=003BH MOV SUM,AX ;存和
JNO NEXT ;无溢出,转NEXT LEA DX,OVER MOV AH,9 INT 21H ;显示’Overflow!’NEXT: MOV AH,4CH INT 21H ;返回DOS MAIN ENDPCHANGE PROC MOV CL,[BX+1] ;实际字符数送CL MOV AL,[BX+2] ;第一个字符送AL MOV CH,AL ;暂存在CH CMP AL,’-’ ;第一个字符是负号吗? JNZ NEXT1 ;不是,转NEXT1 DEC CL ;字符数减1 INC BXNEXT1:ADD BX,2 ;指向第一个数字字符
MOV AX,0 ;清零AX,存二进制数LP1:DEC CL JZ NEXT2 ;若(CL)=0,转NEXT2 MOV DL,[BX];取字符
AND DL,0FH ;转换成BCD码
ADDAL,DL;加到中间结果上
ADCAH,0
MOVDX,10MULDX;*10INCBX;指向下一个字符
JMPSHORTLP1NEXT2:MOVDL,[BX];取个位数
ANDDL,0FH;个位ASCII→未组合BCDADDAX,DX;加个位数,(AX)=001AHCMPCH,’-’;是’-’?JNZNEXT3;该数非负,转NEXT3NEGAX;若为负,求补NEXT3:MOV[DI],AX;存二进制结果
RETCHANGEENDP;CODEENDSENDSTART020A32360D…020A33330D…001A21003B00STR1STR2NUMSUM10个10个‘O’……OVER??040A313234…STR1若键入‘1234’330D‘1’‘2’‘3’‘4’…设键入第1个数为26,第2个数为33,则在内存各变量分配如下:重点掌握:
如何从键盘输入一个字符串
ASCII→未组合BCD→二进制有符号数的运算,对负数和溢出如何处理方法1
计算二进制数中所包含的1000的个数、100的个数、10的个数和1的个数。方法2
除10取余。下面举例介绍第一种方法。流程图如下:③二进制数→BCDYN二进制数
AX令(DL)=0(AX)-1000<0?(DL)+1(AX)+1000(AX)DL存至缓冲区令(DL)=0YN(AX)-10<0?(DL)+1(AX)+10(AX)存DL存AL返回DOS求100的个数,结构同上A汇编程序如下:DATA SEGMENTBNUM DB 270FHDNUM DB 4DUP(?);存放BCD码的缓冲区DATA ENDSCODE SEGMENT ASSUMECS:CODE,DS:DATABINBCD PROC FARBEGIN:MOV AX,DATA MOV DS,AX MOV AX,BNUM;取二进制数
LEA BX,DNUM;BCD码缓冲区首地址送BX
;计算百位的个数
MOVDL,0;千位的个数计数器AGAIN1:SUBAX,1000;(AX)-1000JCNEXT1;若≤0,则退出循环
INCDL;(DL)+1JMPAGAIN1NEXT1:ADDAX,1000;(AX)←(AX)+1000 MOV[BX],DL;存千位的个数
;计算百位的个数
MOVDL,0;百位的个数计数器AGAIN2:SUBAX,100;(AX)-100JCNEXT2INCDLJMPAGAIN2NEXT2:ADDAX,100MOV[BX+1],DL;存百位的个数
MOVDL,0;十位的个数计数器AGAIN3:SUBAX,10;(AX)-10JCNEXT3INCDL JMPAGAIN3NEXT3:ADDAX,10MOV[BX+2],DL;存十位的个数
MOV[BX+3],AL;存个位的个数
MOVAH,4CHINT21HBINBCDENDP;CODEENDS ENDBEGIN④BCD→ASCII
⑤二进制串转换为ASCII码一个二进制位串若要送显示或打印,需把串中每一位(0或1)化为ASCII码。思路:先将目标串全部预置为30H,再把每个二进制位逐位左移至CF,然后判CF=0?若是,取下一位;若不是,将31H送此单元。
流程图如下:初始化用’0’填满串取要转换的数左移1位存入‘1’结束CF=1?转换完?调整指针NN汇编程序如下:DATA SEGMENTNUM DW 6F78HSTRING DB 16DUP(?)DATA ENDS;CODE SEGMENT ASSUMECS:CODE,DS:DATABINCA PROC FARBEGIN: MOV AX,DATA MOV DS,AX MOV ES,AX CLD LEA DI,STRING MOV CX,16;串的长度
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2024版无人机研发与采购合同
- 返校师生核酸检测工作总结
- 慢性病管理系统建设方案
- 二零二四年度公共绿地建设施工合同
- 三元乙丙橡胶防水卷材施工方案
- 2024年度国际出口货物多式联运代理合同
- 2024年度租赁合同:租金押金退还及电器家具归还规定
- 2024年加工承揽合同:航空航天器零部件加工与技术协助
- 2024年度工程设备租赁合同及操作人员派遣服务协议
- 2024年度苯板质量标准买卖合同规定
- CPU卡的主要功能
- 吹风机产业策划方案
- 剖析日本泡沫经济
- 消化系统常见疾病课件
- 财政部土地储备会计核算办法
- 三年级上册心理健康课件-17《灾难面前要冷静》 北师大版
- 2023年企业大监督体系建设方案监督管理体系建设(6篇)
- 抗菌药物培训考试试题及答案9
- SB/T 10614-2011熟制花生(仁)
- GB/T 4257-2004扩孔钻技术条件
- GB/T 30790.6-2014色漆和清漆防护涂料体系对钢结构的防腐蚀保护第6部分:实验室性能测试方法
评论
0/150
提交评论