版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
第4章80x86汇编语言程序设计
本章重点:汇编语言的基本语法规则及其使用方法伪指令语句的格式、类别及功能简化段定义结枸中常用的伪指令8086/8088汇编语言程序设计本章难点:汇编语言语句中使用的各种操作数、表达式、运算符、操作符汇编语言程序设计4.1汇编语言程序和汇编程序4.1.1汇编语言源程序和机器语言目标程序使用汇编语言编写的程序称为汇编语言源程序(简称源程序)。把汇编语言源程序经过翻译,则可得到机器语言程序(目标程序)。如图所示:源程序的汇编过程图
4.1.2汇编和汇编程序
1.汇编把源程序翻译成机器语言目标程序的过程,叫做汇编。
2.汇编程序(ASM)完成汇编任务的程序叫做汇编程序。
3.宏汇编程序(MASM)宏汇编则在基本汇编基础上进一步扩展了功能。能够把源程序中一组汇编语言语句序列定义为一条宏指令且能处理宏指令的汇编程序,叫做宏汇编程序。4.1.3汇编语言程序的语句类型一个汇编语言源程序实际上是为完成某一特定任务按一定语法规则组合在一起的语句序列。语句是汇编语言程序的基本组成单位。指令语句格式:一个语句行是由4个部分组成。
[标号:]指令助记符[操作数][;注释]
例句
Lop:MOVAL,25H1.标号:指令语句的第一部分名字域叫做标号。
2.助记符:这部分是语句中唯一不可缺省的。指令语句的助记符用规定指令语句的操作性质,并对应8086指令系统中实际的操作码。
3.操作数:不同的语句要求有不同的参数。有些语句可以无操作数。
4.注释:注释由分号“;”开始,用来对语句功能加以说明,使程序更容易被理解和阅读。4.28086/8088汇编语言中的标识符、运算符及操作符4.2.1标识符标识符是由程序员自由建立起来的、有特定意义的字符序列。标号和名字皆统一称为标识符。标号和名字的命名规则如下:标号和名字以字母开头由大写字母A~Z小写字母a~z(汇编程序不区分大小写)、数字(0~9)及4个特殊字符(?、@、$、和_等)组成的字符串表示。标号和名字的字符串长度不能超过31个字符。标号和名字的命名不能使用汇编语言中的保留字。凡是8086的指令助记符、伪指令、CPU内部寄存器名等都是保留字。4.2.2运算符运算符用来实现对操作数的相关运算。MASM宏汇编中有3种运算符(算术、逻辑和关系运算符)。
1.算术运算符有+(加)、-(减)、*(乘)、/(除)、MOD(取余)、SHL(左移)、SHR(右移)共7种。算术运算符可用于数值表达式或地址表达式中。例:已知源程序指令格式如下:DAEQU300┆MOVAX,DA—80MOVBX,DAMOD100MOVCX,DA/100MOVDH,01100100BSHR2汇编后,计算表达式形成指令如下:DAEQU300
┆MOVAX,220MOVBX,0MOVCX,3MOVDH,19H2.逻辑运算符是按位操作的AND(与)、OR(或)、XOR(异或)、NOT(非),只适用于数值表达式。例:
MOVAL,NOT0FFHMOVBL,8CHAND73HMOVAH,8CHOR73H
MOVCH,8CHXOR73HANDCX,9ABCHANDFF73H汇编后,计算表达式形成指令为:MOVAL,0;
0FFH取反为0MOVBL,0;
MOVAH,0FFHMOVCH,0FFHANDCX,9A30H
3.关系运算符这类运算符有EQ、NE、LT、GT、LE和GE。关系运算符的两个操作数必须同是数值或同是一个段内的两个存储器地址。比较时,若关系成立(为真),则结果为全“1”,若关系不成立(为假),则结果为全“0”。其结果值在汇编时获得。例:
MOVAX,10HGT16ADDBL,6EQ0110BMOVCX,((PORTLT5)AND100)
OR((PORTGE5)AND111)解:汇编时,形成指令MOVAX,0ADDBL,0FFHMOVCX,100;若满足PORT<5,则PORTLT5逻辑取值为真,PORTGE5逻辑取值为假,即(111AND100)OR(000AND111)
100OR000;若满足PORT>5或PORT=5,应该怎么样?4.2.3操作符
MASM宏汇编中有两种操作符(即分析操作符和合成操作符)操作符完成对操作数属性的定义、调用和修改。
1.分析操作符:又称数值返回操作符,它的运算对象是存储器操作数,其功能为将存储器操作数地址分解为段基址、偏移地址,将存储器操作数的类型值分解为字节、字、近或者远,而返回值是变量或者标号的属性值。分析操作符有SEG、OFFSET、TYPE、LENGTH、SIZE格式:操作符变量/标号功能SEG回送变量/标号的段地址值OFFSET回送变量/标号的偏移地址TYPEVARIABLE/LABEL回送变量/标号的类型值
LENGTH回送变量数据项总数
SIZE回送TYPE和LENGTH的乘积(变量分配的字节存储单元总数)例4-4:
MOVAX,SEGTABLEMOVDS,AXMOVBX,OFFSETTABLEBUF1DB100DUP(0)
BUF2DW200DUP(20H)
BUF3DD100DUP(13)则LENGTHBUF1=100SIZEBUF1=100LENGTHBUF2=200SIZEBUF2=400LENGTHBUF3=100SIZEBUF3=4002.合成操作符合成操作符又称修改属性操作符。常用的合成操作符有PTR、THIS、LABEL等。(1)PTR操作符用来指定或修改存储器操作数的类型属性(原有的段属性和偏移地址属性保持不变)。例句:
ARY1DB0,1,2,3,4;定义字节变量
ARY2DW0,1,2,3,4;定义字变量
MOVBX,WORDPTRARY1[3];将0403H→BXMOVCL,BYTEPTRARY2[6];将03H→CLMOVWORDPTR[SI],4;将0004H送至SI开始的字单元中例句:
DA—BYTEDB20HDUP(0);有32个字节单元为0DA—WORDDW30HDUP(0);有48个字单元为0┆MOVAX,WORDPTRDA—BYTE[10];按字单元操作ADDBYTEPTRDA—WORD[20],BL;按字节单元操作INCBYTEPTR[BX];用BX作指针SUBWORDPTR[SI],30H;用SI作指针JMPFARPTRSUB1;标号SUB1不在本段范围内(2)
THIS操作符THIS操作符与EQU配合使用,可用来定义一个新的变量名或者标号。格式:标号/变量名EQUTHIS距离/类型例句:BWORDEQUTHISBYTE;ARY从新定义为字节类型可按40个字节的缓冲区使用
ARYDW20DUP(?);定义ARY为20个字的缓冲区4.3伪指令及其应用
1.定义:伪指令语句即不是真正的指令语句,它是CPU不执行的语句。在汇编后它本身不产生目标代码,只为汇编程序提供汇编时所需要的控制信息。伪指令的操作(称作伪操作)在汇编过程中完成。
2.语句格式:名字 定义符 操作符;注释常用伪指令大致有下列几种类型:数据定义伪指令;符号定义伪指令;段定义伪指令;过程定义伪指令;定位伪指令;4.3.1数据定义伪指令用于定义一个变量的类型,给存储器赋值,或者仅给变量分配存储单元而不需赋值。一般格式
[变量名]数据定义符操作数[,操作数……];方括中为任选项
DBDWDD其中,DB(DefineByte)——定义该变量为字节类型,给变量分配字节单元或字节串,DW(DefineWord)——定义该变量为字类型,每个操作数占有一个字,即2个字节,在内存中低字节存低地址,高字节存高地址。
DD(Definedoubleword)——定义该变量为双字类型,每个操作数占有两个字。DQ——四个字变量;DT——十个字节变量2.操作数(表达式)的种类(1)常数表达式:例句:DA-BYTEDB50,50H,2*3+4
DA-WORDDW0A34H,4982H(2)问号表达式:表示定义的变量无确定初值?表示仅给变量预先保留相应的存储单元,而不赋予变量某个确定的初值例句:DA-BDB?;给DA-B分配一个字节单元空间,内容未定
DA-WDW?;给DA-W分配一个字单元空间,内容未定(3)字符串表达式:数据定义伪指令也可用于定义字符串。字符串必须放进引号内。例句:STR1DB‘ABCD‘ 以上伪指令把’ABCD’中四个字符的ASCII码值依次存放在STR1,STR+1,STR1+2,STR1+3的字节单元中。也可写成STR1DB‘A’,‘B’,‘C’,‘D’STR2DW‘AB’,‘CD’;注意,这里与上式存放顺序不同,是’BADC’STR3DD‘AB’,‘CD’(4)地址表达式:只适用DW和DD两种伪指令。
例句:
ADRADWAB
;存入变量AB的偏移地址到ADRA字存储单元。
ADRA1DWTAB,TAB+5,TAB+10
;存入以TAB为首的3个等距离的偏移地址到ADRA1开始的存储单元。ADRA2DDTAB
;先存入TAB的偏移地址,再存其段基址,共占4个字节。(5)带“DUP”的表达式:当表中的操作数相同时,可用重复操作符来缩写,“DUP”可以嵌套。指令格式:变量名{DB/DW/DD}表达式1DUP表达式2;其中:表达式1为重复次数,表达式2为重复内容。例:ALL-ZER0DB0,0,0,0,0可写成ALL-ZER0DB5DUP(0)例:
D-B1DB20HDUP(?)
;D-B1分配20H(32)个字节单元,但未赋值
D-B2DB10DUP(‘ABCD’);重复存放10个字符串‘ABCD’,共占用40个字节
D-W1DW10HDUP(4)
;
D-B3DB10HDUP(4DUP(2),7)
D-B4
DB
10HDUP(12H)
D-W2DW10HDUP(1234H)例:试计算下列伪指令中各变量所分配的存储单元字节数和总共占据的存储空间
X1DW20X2DW8DUP(?),10,20X3DD10DUP(?)
X4DB3DUP(?,4DUP(0))
X5DB’HAPPYNEWYEAR!!’总共占据空间图4.3.2符号定义伪指令常用的符号定义伪指令有EQU、“=”、LABEL分别对应于赋值语句、等号语句和定义符号名语句。
(1)赋值语句EQU格式符号名EQU表达式例:CREQU0DH;将0DH赋予符号名CR
LFEQU0AH;
STREQU‘COMPUTER’;为字符串定义新的名字
COUNTEQUCX;为寄存器CX定义新的符号名COUNTLDEQUMOV;为指令MOV定义新的符号名
LD注意:
①用EQU定义是符号定义并不占据内存单元。
②由EQU伪指令定义的符号不能使用汇编语言的保留字。
③同一源程序中,用EQU定义过的符号名,不能再重新定义。
(2)等号语句“=”该语句的功能与EQU的功能基本相同,区别在于可以对同一个符号名重复定义,用新的数值表达式重新赋值。格式:名字=表达式例句:COUNT=10MOVCX,COUNT;CX←10┆COUNT=COUNT+1MOVBX,COUNT;BX←11┆(3)定义符号名语句LABEL
格式:符号名LABEL类型例句:
AGAINFLABELFAR;定义标号AGAINF的属性为FARAGAIN:PUSHAX;标号AGAIN的属性为NEAR注:AGAIN标号名可以不用定义直接出现并使用4.3.3段定义伪指令(SEGMENT/ENDS)在汇编语言源程序中用来定义逻辑段。1.常用的段定义伪指令为SEGMENT/ENDS和ASSUME等。(1)SEGMENT/ENDSSEGMENT伪指令位于一个逻辑段的开始,用来定义一个逻辑段,给该逻辑段赋予一个段名。ENDS伪指令则表示该逻辑段的结束。这两条伪指令总是成对出现,二者前面的段名必须一致。格式:段名SEGMENT[定位类型][组合方式][‘类别名’]┆
段名ENDS①定位类型:用来确定逻辑段的边界在存储器中的位置。定位类型下面仅列举两种:PAGE——
表示逻辑段从页(PAGE)边界开始。通常一页为256字节。PARA——
表示逻辑段从一个节(PARAGRAPH)边界开始,通常一个节包括有16个字节。如果定位类型为缺省项,则默认其为PARA。②组合方式:用于如何组合几个不同的逻辑段。组合方式下面列举4种:NONE——不组合的独立段。即不同程序中具有相同类别名的逻辑段分别作为不同的逻辑段装入内存,不进行组合。PUBLIC——对于不同程序模块中的逻辑段,只要具有相同的类别名,就把这些同名段顺序连接成为单个连续的逻辑段装入内存。STACK——其含义与PUBLIC基本一样,不过组合方式STACK仅限于作为堆栈区的逻辑段使用,在运行时就是堆栈段寄存器SS所指物理段,且SP指向该段的末地址加1。AT表达式——
表示本逻辑段根据表达式求值的结果定位段基址(与ORG配合使用)例如AT4A00H,表示本段的段基址为4A00H则本段从存储器的物理地址4A000H开始装入。
③‘类别名’:类别名是用单引号括起来的字符串。必须放在单引号‘’内。(2)ASSUME
用来指定段寄存器与段的关系。格式:ASSUME段寄存器名:段名[,段寄存器名:段名[,…]]例句:CODESEGMENTASSUMECS:CODE,DS:DATA,SS:STACKASSUME使用方式基本不变,若没有定义堆栈段就可以不要SS:STACK,没有定义数据段就可以不要DS:DATA(3)END:END伪指令用在源程序的最后,用以表示整个源程序的结束。格式:END[表达式];表达式一般为过程名或者END[入口地址]4.3.4过程定义伪指令(PROC/ENDP)
PROC是过程定义伪指令,ENDP是过程结束伪指令。过程定义伪指令格式:过程名PROC[NEAR]/FAR┆RET过程名ENDP过程调用时用CALL过程名4.3.5当前地址计数器($)符号$表示地址计数器的当前值。例句:DATASEGMENTBUFDB10H,20H,30HCOUNTEQU$-BUF;常量COUNT的值就是当前待分配的地址值减去变量BUF的地址值,本例中实际上是BUF数据单元的长度3。4.3.6定位伪指令(ORG)ORG的功能是将当前地址计数器设置成数值表达式的值。也就是地址值重定位。格式:ORG数值表达式或者ORG$+表达式例:DATASEGMENTORG1000HXDB20H,30H;X的地址从1000H处开始分配ORG$+20H;当前地址为1002HCONSTEQU0ABCDH;CONST的地址从1022H处开始分配4.4宏指令及其应用一条宏指令可包括若干条指令语句或伪指令语句。宏指令一旦定义,可以像其他指令一样使用。4.4.1宏定义由于宏指令不是指令系统提供的,所以必须先定义后才能使用,其一般格式为:宏指令名MACRO[形式参数1][,形式参数2]…┆
;宏指令体
┆
ENDM
例:定义一条宏指令,用来实现将累加器AL内容逻辑右移4次(位)。若宏指令引入两个形式参数,n和Reg,则宏定义格式如下:
SHIFTMACROn,Reg
;n表示移位次数,应>1
MOVCL,n;Reg
代表要移位的寄存器
SHRReg,CL
ENDM宏指令可以理解为整体替换。4.4.2宏调用例:MOVAL,06HSHIFT44.5DOS和BIOS功能调用4.5.1DOS功能调用DOS(DISKOPERATINGSYSTEM)是PC机的单任务、单用户的磁盘操作系统。DOS常用的软中断指令主要有21H,功能调用几乎包括了整个系统的功能。1.DOS功能调用的方法所有的DOS功能调用时必须有下列3个方面内容:提供功能调用的入口参数和出口参数;入口参数是指调用前要对相应寄存器输入指定的初始值,出口参数是指调用后的结果存放在相应的寄存器中。将子程序功能号送入AH或AX;所有子程序从1号开始编号,成为DOS功能调用号。执行软中断指令INT21H。下面介绍INT21H类型中最常用的DOS功能调用(1)DOS键盘功能调用从键盘输入单个字符(功能号01H、08H、06H、07H)
从键盘输入字符串(功能号0AH)(2)DOS显示功能调用显示器上显示单个字符(功能号02H、06H)显示器上显示字符串(功能号09H)(3)DOS打印功能调用(功能号05H)(4)日期与时间设置功能调用(功能号2BH、2AH、2DH、2CH)(5)结束程序返回操作系统功能调用(功能号4CH)2.常用DOS功能调用举例例:编写完成从键盘输入字符串存至内存缓冲区并显示该字符串的汇编语言源程序。解:
DATASEGMENT;定义数据段
BUFDB5;输入缓冲区长度最多可容纳5个字符
DB?;实际输入的字符个数
DB5DUP(?),‘$’DATAENDS
CODESEGMENT;定义代码段
ASSUMECS:CODE,DS:DATA;START:MOVAX,DATA;初始化DSMOVDS,AX;
LEADX,BUF;要求DS:DX指向输入缓冲区BUF处
MOVAH,0AH;将DOS功能号0AH装入AH。
INT21HLEADX,BUF+2MOVAH,09H;将DOS功能号09H装入AH,显示以“$”结尾的字符串,字符串在DX中
INT21HMOVAH,4CH;程序结束,返回DOSINT21HCODEENDSENDSTART
4.5.2BIOS中断调用常用的BIOS中断类型,如:INT10H显示器中断调用(AH=00H~0FH)
INT14H串行通信口功能调用(AH=00H~03H)
AH=00H——通信口初始化
AH=01H——通信口输出
AH=02H——通信口输入INT16H键盘中断调用(AH=00H~02H)
AH=00H——读键盘输入字符
AH=01H——检测键盘是否输入字符
AH=02H——读键盘当前状态INT17H打印机中断调用(AH=00H~02H)
AH=00H——打印一个字符(AL=打印字符的ASCII码)1.BIOS程序的调用方法步骤如下:将功能号送入AH或AX中,查阅BIOS功能调用参数表,查得BIOS的中断类型号,取得功能号。设置入口参数。执行软中断指令INTN2.常用BIOS中断调用举例例:要求在640*350且16色显示方式下,画一矩形框,框的左上角坐标(100,50)和右下角坐标(400,200)。解:CODESEGMENTASSUMECS:CODESTART:MOVAL,0FHMOVAH,00HINT21HMOVCX,100MOVDX,50LL0:MOVAH,0CHINT10HINCCXCMPCX,400JNZLL0INCDXCMPDX,200JNZLL0JMP$MOVAH,4CHINT21HCODEENDSENDSTART4.68086/8088汇编语言程序的基本结构框架4.6.1汇编语言源程序基本结构特点汇编语言源程序由若干逻辑段组成,各逻辑段都有一个段名。其中:代码段——是程序的主体.存放源程序中CPU必须执行的所有机器指令代码。数据段——存放程序中各类数据。附加段——为数据段的补充,并非所有程序都有。堆栈段——程序中可以定义,也可以不定义,而利用系统中的堆栈段。以上各段的逻辑段基址分别存放在CS、DS、ES和SS四个段寄存器中。4.6.2汇编语言源程序的基本结构框架目前较为常用是两种格式:完整段定义格式;这是传统的汇编语言源程序格式。简化段定义格式;在完整段定义结构的基础上经过简化而得。1.完整的段定义格式(1)完整的段定义格式要求每个段有SEGMENT和ENDS这一对伪指令来实现。(2)堆栈段、数据段和代码段的段名分别定义为STACK、DATA和CODE,并非一定必须如此,也可取用其它名称,如:SEG1,SEG2,SEG3等。(3)使用ASSUME(段寄存器分配)伪指令用来指定某段分配给哪个段寄存器。由于伪指令不由CPU执行,故它并不能把段地址装入段寄存器中,尚需对段寄存器进行初始化。2.简化的段定义格式
(1)定义内存模式伪指令.MODEL在使用简化段定义之前,必须首先利用.MODEL伪指令指明程序所使用的内存模式。内存模式是指程序中代码段和数据段在存储器中存放的方式。格式:.MODEL存储模式(2)简化段定义伪指令用来定义代码段、数据段和堆栈段等。①.CODE[NAME]——定义代码段NAME用于自定义段名。②.DATA——定义已初始化的数据段,默认的段名是—DATA。③.DATA?——定义未初始化的数据段。④.STACK[SIZE]——定义堆栈段,[]可以指定堆栈段的长度(字节数)。默认的段名是STACK。⑤.STARTUP——指示程序开始伪指令并初始化DS、SS、SP的值。⑥.方式伪指令:指定该指令系统的类型。例如:.8086,.386,.386P,.486等⑦.EXIT——返回DOS系统伪指令。能终止程序执行并返回DOS。⑧
END——汇编结束伪指令例:将存储区BUF1中100字节的源数据串,搬移到存储区BUF2的目的串中。解:源程序如下:
MODELSMALL;小型模式内存
80386;80386方式
STACK100H.;堆栈段开始,栈长度为100HDATA;数据段开始
BUF1DB100DUP(12H);源数据串
BUF2DB100DUP(?);目的串数据
CODE;数据段结束,代码段开始
STARTUPCLDMOVSI,OFFSETBUF1;设置源串指针
MOVDI,OFFSETBUF2;设置目的串指针
MOVCX,64H;设置计数初值
REPMOVSB;重复串传送
EXIT0END4.6.3汇编语言源程序正确返回DOS操作系统的方法(1)在程序代码段的开头,设置下面3条语句:
PUSHDSMOVAX,0PUSHAX;压入返回地址
┆然后在程序退出处安排一条RET(返回)指令,则可返回DOS.(2)在程序代码段的结尾处,安排如下两条指令:
MOVAH,4CH;(或MOVAX,4C00H)
INT21H4.780x86汇编语言程序设计汇编语言程序基本结构形式有:顺序结构、分支结构、循环结构和子程序。
4.7.1顺序结构程序设计例;试编写一个完整格式的汇编语言程序,要求在屏幕上显示“UNIVERSITYOFELECTRONICSCIENCEANDTECHNOLOGYOFCHINA”。解:SSEGSEGMENTPARASTACK’STACK’DB40HDUP(0);
SSEGENDSDSEGSEGMENTPARAPUBLIC’DATA’MESSDB‘UNIVERSITYOFELECTRONICSCIENCEANDTECHNOLOGYOFCHINA,’DB‘ZHONGSHANINSTITUTE$’DSEGENDSCSEGSEGMENTPARAPUBLIC’CODE’STARTPROCFARSTARTPROCFARASSUM,EDS:DSEG,SS:SSEG,CS:CSEG,ES:DSEGPUSHDS;MOVAX,0;PUSHAX;MOVAX,DSEG;MOVDS,AX;MOVES,AX;MOVDX,OFFSETMESS;
MOVAH,9;INT21H;RET;STARTENDPCSEGENDSENDSTART例:从端口地址为0250H的I/O设备输入80个字节数据存入到附加段的字节数组ARY中。
解:MODELSMALL;
386;设置32位的386汇编方式
STACK;定义堆栈段
DATA;定义数据段
ARYDD20DUP(?)CODE;定义代码段
START:MOVAX,DATAMOVES,AXMOVDI,OFFSETARY;用DI寻址输入的数据
MOVDX,0250H;寻址I/O设备
CLD;增址方向
MOVCX,20;装入计数初值
REPINSD;输入字节数据至字节数组ARYEXITENDSTART4.7.2分支结构程序设计汇编语言中用条件转移指令和无条件转移指令来实现分支程序结构。分支程序有:二分支、三分支或多分支等。1.利用比较/条件转移指令实现两分支
2.利用逻辑运算(AND、OR、TEST)指令影响标志位实现三分支。例:编写一个程序把三个无符号单字节数从大到小进行排列。解:排序算法中有三个分支结构,其排序程序流程图如图所示。三个分支结构程序流程图源程序如下:STACK1SEGMENTSTACK’STACK’
DW64HDUP(?)STACK1ENDSDATASEGMENTBUFDB84H,32H,56H;待排序数据DATAENDSCODESEGMENTASSUMECS:CODE,DS:DATA,SS:STACK1START:MOVAX,DATAMOVDS,AX;初始化DSMOVSI,OFFSETBUF;设置地址指针
MOVAL,[SI];将数据由内存读入寄存器
MOVBL,[SI+1]MOVCL,[SI+2]CMPAL,BL;比较AL与BLJAENEXT1;第1分支结构XCHGAL,BL;AL内容大NEXT1:CMPAL,;比较AL与CLJAENEXT2;第2分支结构XCHGAL,CLNEXT2:CMPBL,CL;比较BL与CLJAENEXT3;第3分支结构XCHGBL,CLNEXT3:MOV[SI],AL;存结果到内存
MOV[SI+1],BL;
MOV[SI+2],CL;
MOVAH,4CHINT21HCODEENDSENDSTART3.利用跳转表实现多分支例:设有8个子程序,已知其入口地址分别为SUB0,SUB1,…SUB7(同在一个段内)依次放在ADRTAB开始的地址表中.每个地址占两个字节。低字节在低地址,高字节在高地址。当键盘输入0-7中任一数字i时,便可分支到相应的子程序中执行,实现多路分支。解:(1)首先建立一个跳转表,表中存放每个子程序的入口地址。利用此表可找到存放子程序入口地址的位置(叫做查表地址)设地址表基地址为ADRTAB.
(2)根据键入的数字i计算查表地址:查表地址=跳转表首地址+偏移地址=ADRTAB+2*i(i=0~7中任一值)子程序入口地址表
程序流程图
源程序如下:
DSGSEGMENTADRTABDWSUB0,SUB1,SUB2,SUB3,SUB4,SUB5,SUB6,SUB7;定义入口地址表
KEYINDB?
DSGENDSSSGSEGMENTPARASTACK‘STACK’DW40DUP(?)
SSGENDSCSGSEGMENTASSUMECS:CSG,DS:DSG,SS:SSG
STARTPROCFARPUSHDSMOVAX,0PUSHAXMOVAX,DSGMOVDS,AXMOVAH,01;从键盘输入0~7中的一个数
INT21H;键盘输入的ASCⅡ码在AL中COMPUT:MOVAH,0;2*i
ANDAL,0FHSHLAL,1MOVBX,OFFSETADRTABADDBX,AX;求查表地址
JMPWORDPTR[BX];转入相应入口地址SUB0:;8个例行子程序SUB1:┆SUB7:
RETSTARTENDPCSGENDSENDSTART4.7.3循环结构程序设计当要重复执行一段程序时,利用循环指令LOOP,LOOPZ和LOOPNZ或条件转移指令来实现重复操作。循环结构可以简化程序结构。循环程序结构通常由以下4个部分组成:
1.初始化部分:该部分工作是置循环初值(即为循环作准备),包括设置循环计数器,地址指针初值和存放结果单元的初值等。2.循环体:要被重复执行的程序段。是循环结构程序的核心。3.循环修改部分:为执行下一次循环而修改某些参数。如循环变量加一、地址指针和循环次数改变等。4.循环控制:根据给定的循环次数和循环条件判断是否结束循环。若未结束则重复执行循环体和修改部分,否则退出循环。循环程序基本结构图例:在显示屏幕上连续输出字符0-9。试编程实现。解:(1)使用DOS功能子程序2号,实现输出一个字符,并把该字符的ASCII码送至寄存器DL。(2)使用BL寄存器存放十进制数,其初值为0,每循环一次BL内容加1,增量后用DAA指令调整,以保证BL内容始终为十进制数。(3)为了使输出的字符间有间隔,在每次循环中输出一个0-9的字符和一个空格。(4)程序流程图如图所示。此为“先执行—后判断”结构。(5)源程序如下:STACK1SEGMENTPARASTACK’STACK’
DB50DUP(?)STACK1ENDSCSEGSEGMENT ASSUMECS:CSEG,SS:STACK1STARTPROCFARBEGIN:PUSHDS MOVAX,0 PUSHAX MOV BL,0 PUSHBXGOON:MOVDL,20H;显示输出空格字符
MOVAH,2 INT21H POPBX MOVAL,BL INCAL;增量后十进制调整
DAA ANDAL,0FH MOVBL,AL ORAL,30H MOVDL,AL;转换为ASCII码,输出;一个0~9之间的字符MOVAH,2 INT21H MOVCX,0FFFFHAGN:DECCX;延时
JNEAGN JMPGOON;循环运行
RETSTARTENDPCSEGENDS ENDBEGIN 所谓逻辑尺是指存储单元,其中每一位为0或为1,可用来作为判断分支和循环的逻辑标志,犹如尺子一样。下面以两分支为例,说明逻辑尺的具体应用。例:有某温度测量系统,现已采集16次温度参数,存放于缓冲区BUF。每个温度参数都与温度标称值存在微小误差Δ,则需进行加/减温度补偿即须执行两种温度补偿函数:用COMP0实现“加1”,用COMP1实现“减1”计算,用加或者用减需由逻辑尺中的标志位来确定。试编此程序。解:据题意,设总共温度补偿须循环16次。室温25℃为标准值。其中第0,1,4,5,6,10,11,15次要求执行COMP0(+1)计算,其余第2,3,7,8,9,12,13,14次要求执行COMP1(-1)计算。则逻辑尺LOGIR的标志位应设置为0111001110001100B=738CH设i表示标志位位序。源程序如下:DATA1SEGMENTBUFDB18H,18H,1AH,1AH,18H,18H,18H,1AH
;共16个温度参数
DB1AH,1AH,18H,18H,1AH,1AH,1AH,18HRESDB16DUP(?)LOGIRDW738CHDATA1ENDSCODE1SEGMENT ASSUMECS:CODE1,DS:DATA1START:MOVAX,DATA1
MOVDS,AX LEASI,BUF
LEADI,RES MOVBX,LOGIR MOVCX,16AGA: LODSB SHLBX,1 JNCCOMP0COMP1:SUBAL.1
JMPNEXTCOMP0:ADDAL,1NEXT: STOSB LOOPAGA MOVAH,4CH INT21HCODE1ENDS ENDSTART
上例程序流程图☆例:将内存首地址为BUF1开始的10个带符号字节数,将其由小到大的次序排列。解:采用冒泡法实现排序。使用双重循环结构。内循环完成前后两个数两两比较,外循环控制比较轮数。源程序如下:
.MODEL SMALL.DATABUF1DB 34H,12H,89H,… .CODE STARTUP MOVDX,9X1:MOVCX,DX MOVSI,0X2: MOVAL,BYTEPTRBUF1[SI] CMPAL,BYTEPTRBUF1[SI+1]
JLE NEXT
XCHGAL,BUF1[SI+1]
MOVBUF1[SI],ALNEXT: INC SI
LOOPX2 DECDX JNZ X1 EXIT END3.多重循环程序设计
例:软件延时程序执行程序中的每条指令都有一定的执行时间,因此利用软件可以实现延时。试设计要求延时1S的延时程序。解:利用双重循环实现。子程序如下:SOFTDLYPROC;指令执行时间(时钟周期数)
MOVBL,100;4TDELAY:MOVCX,n;4T(内循环延时10ms)WAIT:LOOPWAIT;17T或者5T
DECBL;3TJNZDELAY;16T或者4TRET;20TSOFTDLYENDPt内=0.01=10ms=[17(n—1)+5+4]*T(8088CPU的时钟周期≈210ns)∴n=2801(即内循环CX的控制次数)
t外=(BL)*t内+(BL)*19T=100*(t内+19T)≈1S可以看出:内循环中CX由2801减至0(BL维持不变)由此可实现10ms的延时。外循环进行100次,共可实现1000ms的延时。4.7.4子程序结构程序设计子程序又称过程。是具有独立功能的模块。在程序设计中,为了使结构尽量简单,实现代码复用,增强可读性,提高编程效率而设计的一种程序结构。子程序常采用模块化的程序设计方法,即把程序中的某些具有独立功能的部分编写成独立的子模块,这种程序模块称为“子程序”或者“过程”。1.子程序概述对于无规律的重复执行,如键盘输入处理、数制转换、代码转换等,为避免编制相同程序的重复性工作,节约存储空间,可把它独立出来,附加一些其它的指令,将其编制成可以反复调用的公用的独立程序段,并通过适当方法把该程序段与其它程序段连接起来。这种程序设计的方法称为子程序设计,被独立出来的程序段称为子程序。调用子程序的程序称为主程序或调用程序。主程序与子程序的连接关系(1)子程序的调用与返回子程序调用指令:CALL和返回指令:RET。(2)主程序与子程序间的参数传递。主程序与子程序相互传递的信息称为参数。传递的参数可以是信息本身,也可以是信息的地址,其传递基本方法有如下3种:
①寄存器传递参数
②堆栈传递参数:这是最重要的方法之一。
③存储单元传递参数:
(3)保护现场与恢复现场子程序不可避免地要使用一些寄存器,因为主程序和子程序是分别编写的,所用的寄存器可能发生“撞车”。因此子程序执行后,某些寄存器的内容会发生变化,如果主程序在这些寄存器中已经存放有用的信息,则从子程序返回主程序后,主程序运行势必因原存信息被破坏而出错。在使用这些寄存器之前,将其内容推入堆栈保存起来,而在使用之后返回主程序之前退出,将堆栈内容弹回寄存器,前者称为保护现场,后者称为恢复现场。保护现场与恢复现场的操作可以在主程序中完成,也可以在子程序中完成。一般情况下是在子程序中完成。保存和恢复操作可以通过进栈指令和出栈指令实现。2.子程序嵌套与递归子程序一个子程序也可作为主调程序去调用另一个子程序的过程,称为子程序嵌套。一个子程序作为主调程序去调用自身的过程,称为子程序递归。(1)子程序嵌套。主程序X调用子程序Y而子程序Y又调用子程序Z,因此,子程序Y对于主程序X来说是子程序,而对于子程序Z来说则是主程序。以上XYZ三个程序之间的调用和返回关系也称为子程序嵌套。子程序的嵌套结构子程序的递归结构
(2)递归子程序。在子程序嵌套情况下,若一个子程序所调用的子程序就是它本身,这种调用称为递归调用,该子程序称为递归子程序。递归子程序往往用于数学领域内的对函数的递归定义如求阶乘及其它较复杂的运算。3.子程序设计举例例:试用寄存器传递参数法编写一个子程序,实现大写字母到小写字母的转换。解:已知小写英文字母a、b、c…x、y、z的ASCII码与大写英文字母A、B、C…X、Y、Z的ACSII码相差十六进制常数20H,故要实现本题转换必须加上20H。源程序如下:STATASEGMENTPARASTACK‘STACK’DW20HDUP(?);STATAENDSDATAASEGMENTSTR1DB‘A’,‘B’‘C’,‘D’‘E’,‘A’,‘B’LENEQU$—STR1STR2DBLENDUP(?);用来存放转换后的小写字母。DATAAENDSCODEESEGMENTASSUMECS:CODEE,DS:DATAA,SS:STATASTART:MOVAX,DATAAMOVDS,AXMOVBX,OFFSETSTR1MOVCX,LENAGN:MOVAL,[BX]CALLSUBRMOV[BX+LEN],ALINCBXLOOPAGNEXIT:MOVAH,4CHINT21HSUBRPROCNEARCMPAL,‘A’JBEXIT1CMPAL,’Z’JAEXIT1ADDAL,20HEXIT1:RETSUBRENDPCODEEENDSENDSTART例:试用堆栈传递参数法.编写求某数据区中无符号字数据最大值的子程序及其调用程序。解:要求参数通过堆栈传递,先设定子程序存取参数都由BP寄存器间址.源程序如下:STACKKSEGMENTPARASTACK‘STACK’DW32DUP(0)STACKKENDSDATAASEGMENTBUF
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2026届上海市复旦附中浦东分校数学高一上期末调研试题含解析
- 班会周年活动策划方案(3篇)
- 社区食堂休息驿站管理制度(3篇)
- 酒店餐厅取消订单管理制度(3篇)
- 风动锚杆钻机管理制度(3篇)
- 《GA 862-2010机动车驾驶证业务信息采集和驾驶证签注规范》专题研究报告
- 兼职培训教学课件
- 养老院信息化管理与服务制度
- 企业商务合作流程规范制度
- 企业财务预算管理制度
- 湖南省2025-2026学年七年级历史上学期期末复习试卷(含答案)
- 2026年中国热带农业科学院南亚热带作物研究所第一批招聘23人备考题库完美版
- 2026新疆阿合奇县公益性岗位(乡村振兴专干)招聘44人考试参考试题及答案解析
- 纺织仓库消防安全培训
- 器官移植术后排斥反应的风险分层管理
- 虚拟电厂关键技术
- 事业单位清算及财务报告编写范本
- 护坡绿化劳务合同范本
- 临床绩效的DRG与CMI双指标调控
- 护坡施工安全专项方案
- 2026年湛江日报社公开招聘事业编制工作人员备考题库及完整答案详解
评论
0/150
提交评论