四章汇编语言程序设计.ppt

上传人:sccc 文档编号:5387367 上传时间:2023-07-02 格式:PPT 页数:98 大小:1.08MB
返回 下载 相关 举报
四章汇编语言程序设计.ppt_第1页
第1页 / 共98页
四章汇编语言程序设计.ppt_第2页
第2页 / 共98页
四章汇编语言程序设计.ppt_第3页
第3页 / 共98页
四章汇编语言程序设计.ppt_第4页
第4页 / 共98页
四章汇编语言程序设计.ppt_第5页
第5页 / 共98页
点击查看更多>>
资源描述

《四章汇编语言程序设计.ppt》由会员分享,可在线阅读,更多相关《四章汇编语言程序设计.ppt(98页珍藏版)》请在三一办公上搜索。

1、第四章 汇编语言程序设计,第四章 汇编语言程序设计,在了解和熟悉了86系列指令系统的基础上,本章将介绍宏汇编语言程序的结构,伪指令,以及程序设计的一般过程和各种基本程序结构,然后介绍了系统功能调用,最后给出大量的编程实例。,4.1 汇编语言语句,语句是汇编语言源程序的基本组成单位。一个汇编语言源程序中有3种基本语句:指令语句、伪指令语句和宏指令语句。前两种是最常见、最基本的语句。指令语句和伪指令语句不仅在程序中的功能不同,而且实现其功能的方法和时间也是不同的。1、指令语句 指令语句就是计算机中指令系统的各条指令,每条指令语句在汇编时都产生一个供CPU执行的机器目标代码。计算机中每条指令语句表示

2、一种基本功能,这些基本功能是在程序运行期间由计算机硬件来实现的。一条指令语句由四个字段组成,其一般格式如下:标号:指令助记符操作数;注释,一、汇编语言语句种类及其格式,2、伪指令语句 伪指令语句指示汇编程序在汇编源程序时完成某些工作,比如完成数据定义、分配存储区、指示程序结束等。伪指令属于汇编控制命令,它所指示的操作是由汇编程序在汇编源程序时完成的,在汇编时,它不产生目标代码,在将源程序汇编成目标程序后,它就不复存在了。由上可知,伪指令语句与指令语句的主要区别是:伪指令语句经汇编后不产生机器目标代码,而指令语句经汇编后将产生相应的机器目标代码;伪指令语句所指示的操作是在程序汇编时完成的,而指令

3、语句的操作必须在程序运行时才能完成。一条伪指令语句也由四个字段组成,其一般格式如下:符号名伪指令符操作数;注释,4.1 汇编语言语句,一、汇编语言语句种类及其格式,(1)符号名 符号名在伪指令语句中是一个可选项,符号名后面没有冒号,符号名可以是常量名、变量名、过程名等。(2)伪指令符伪指令符指定汇编程序要完成的具体操作,它是伪指令语句的核心部分,如数据定义伪指令DB、DW、DD,段定义伪指令SEGMENT,定义过程伪指令PROC等等。(3)操作数 伪指令中的操作数可以是常数、字符串、变量、表达式,其个数由具体的伪指令决定,各个操作数之间用“,”分隔。(4)注释 伪指令语句的注释也是可选项,需要

4、时必须以“;”开始。,4.1 汇编语言语句,一、汇编语言语句种类及其格式,3、标识符 指令语句中的标号和伪指令语句中的符号名统称为标识符。它们由若干字符组成,标识符的组成规则如下:(1)一个标识符由1-3个字符组成。(2)组成标识符的字符可以是字母(A-Z或a-z)、数字(0-9)、专用字符(“?”、“”、“”、“$”、“下划线_”)。(3)除数字外,上述其余字符均可作为标识符的首字符,“”只能作为标识符的首字符。(4)不能使用属于系统的专用保留字。,4.1 汇编语言语句,一、汇编语言语句种类及其格式,二、汇编语言数据与运算符,4.1 汇编语言语句,1、常量常量是没有任何属性的纯数值,它的值在

5、汇编期间已能完全确定,且在程序运行中也不会发生变化。常量分为数值常量、字符串常量和符号常量,它主要用于指令语句中的立即数或伪指令语句中给变量赋初值等。1)数值常量数值常量分为整数和实数。例如:11100011B,45693,0FF2AH,356703Q都是正确的整数形式,又如:543.567,45.23,1.2E2,45.4E9都是正确的实数形式。2)字符串常量字符串常量是用单引号括起来的一个字符或多个字符。字符串常量以单引号中各字符的ASCII码形式存储在内存中,如H,在内存中就是41H,12就是31H,32H。使用时可在单引号内直接写字符序列,如12AB,也可写字符的ASCII码,ASCI

6、I码之间用逗号分隔(此时不需要用单引号),如31H,32H,41H,42H表示字符串12AB。3)符号常量符号常量是指用EQU伪指令或赋值语句“=”定义过的符号名,可作操作数项或在表达式中使用。,4.1 汇编语言语句,二、汇编语言数据与运算符,2、变量 在汇编语言中,变量是一个数据存储单元的名称,即数据存放地址的符号表示。它代表存放在某些存储单元的数据,这些数据在程序运行期间随时可以改变。为方便访问变量,在程序中通过变量名来使用变量。(1)变量的定义 变量通常在数据段或附加段中使用数据定义伪指令来定义,定义变量就是给数据分配存储单元,有时为存储单元赋予一个变量名,并可同时为这些存储单元预置初值

7、。数据定义伪指令的格式为:变量名 DB(DW、DD、DQ、DT)表达式1,表达式2,,4.1 汇编语言语句,二、汇编语言数据与运算符,其中:变量名是可选项,它仅代表所定义数据存储区第一个单元的地址;DB、DW、DD、DQ和DT是伪指令符,具体一条数据定义伪指令取5种之一。表达式1,表达式2是给变量或指定的存储单元赋予初值,它们有以下几种形式:(a)数值表达式(b)字符串表达式(c)?表达式(d)地址表达式(只适用于DW和DD这两种数据定义伪指令)(e)带DUP的表达式(2)变量的属性 由于存储器是分段使用的,因而源程序定义的变量具有3个属性:(a)段属性(SEG)(b)偏移属性(OFFSET)

8、(c)类型属性(TYPE),二、汇编语言数据与运算符,4.1 汇编语言语句,(3)变量的使用 定义后的变量,在程序中的引用有两种情况:(a)在指令语句中,采用存储器操作数的几种寻址方式,除寄存器间接寻址方式不使用变量名外,其余各种寻址方式均可使用变量名。例如,某数据段已定义一变量ARRAY:ARRAY DW 5000H,4000H(b)在数据定义伪指令DW和DD中,操作数字段可直接引用已定义过的变量名。如:A DB 50H,40H B DW A C DD B,4.1 汇编语言语句,二、汇编语言数据与运算符,3、标号 标号是一条指令语句的符号地址,在汇编源程序中,只有在需要转向一条指令语句时,才

9、为该指令语句设置标号,以便在控制转移指令中直接引用这个标号。标号一般在代码段中定义和引用。由于标号代表了指令的符号地址,所以标号也有3个属性:(a)段属性(SEG)。标号的段属性是指标号定义所在段的段首地址。(b)偏移属性(OFFSET)。标号的偏移属性是指标号所在段的段首地址到该标号的字节距离。(c)类型属性(TYPE)。标号的类型属性表示了它的转移特性,即该标号是作为段内还是段间转移(或调用)指令的目标地址。标号的类型属性有2种:NEAR类型和FAR类型。,4.1 汇编语言语句,二、汇编语言数据与运算符,4、表达式和运算符汇编语言的指令语句和伪指令语句中,表达式是操作数项的常见形式,表达式

10、是由常量、变量、标号用运算符连接而成有意义的式子。表达式分为数值表达式和地址表达式,任一表达式的值只计算一次,表达式的计算是在源程序汇编过程中进行的,而不是在程序运行中进行的,汇编程序将表达式计算后得到一个数值或一个地址。在8086汇编语言中,运算符分为:算术运算符、逻辑运算符、关系运算符、数值回送运算符、属性运算符和字节分离运算符。,4.1 汇编语言语句,二、汇编语言数据与运算符,(1)数值表达式 数值表达式是由常量与算术运算符、逻辑运算符或关系运算符构成的有意义的式子。数值表达式在汇编期间进行运算,运算结果为一数值常量,它只有大小而没有属性。(2)地址表达式 地址表达式是由常量、变量、标号

11、、寄存器(BX、BP、SI、DI)内容(用寄存器名加方括号表示)和运算符组成的有意义的式子。单个的变量、标号、寄存器的内容是地址表达式的特例。地址表达式中可以使用算术运算符中的“+”、“-”运算符、关系运算符、属性运算符、数值返回运算符和分离运算符。在地址表达式中,常用的形式是:变量常量。,4.1 汇编语言语句,二、汇编语言数据与运算符,(a)算术运算符:+,-,*,/,MOD,SHL,SHR。(b)逻辑运算符:AND,OR,XOR,NOT。(c)关系运算符:EQ,NE,LT,LE,GT,GE。当关系成立时,结果为0FFFFH,当关系不成立时,结果为0。(d)数值回送运算符:SEG,OFFSE

12、T,TYPE,SIZE,LENGTH。,4.1 汇编语言语句,二、汇编语言数据与运算符,OFFSET/SEG 变量/标号功能:回送变量或标号的偏址/段址TYPE 变量/标号/常数 DB DW DD DF DQ DT NEAR FAR 常数 1 2 4 6 8 10-1-2 0LENGTH 变量功能:回送由DUP定义的变量的单元数,其它情况回送1SIZE 变量功能:LENGTH*TYPE,(3)表达式运算符,(5)属性运算符:PTR,段操作符,THIS,SHORT。类型 PTR 表达式 MOV WORD PTR BX,5段操作符 MOV ES:BX,ALSHORT 标号 JMP SHORT NE

13、XTTHIS 类型 TA EQU THIS BYTE TD DW 1234H NEXT EQU THIS FAR MOV AX,2(6)分离运算符:LOW,HIGH。HIGH和LOW CONS EQU 1234H MOV AH,HIGH CONS MOV AL,LOW CONS,4.1 汇编语言语句,二、汇编语言数据与运算符,4.2 伪指令,1 数据定义伪指令2 符号定义伪指令3 段定义伪指令SEGMENT/ENDS4 假定伪指令ASSUME5 定位伪指令ORG与地址计数器($)6 过程定义伪指令PROC/ENDP7 源程序开始和结束伪指令,常用的数据定义伪指令有DB,DW,DD,DQ,DT。

14、格式:变量名 数据定义伪指令 表达式,功能:定义数据存储区,类型由数据定义伪指令确定,初值由表达式给定。,例:DATA_BYTE DB 10,4,10H,?DATA_WORD DW 100,100H,-5,?,1 数据定义伪指令,4.2 伪指令,例:ARRAY DB HELLO DB AB DW AB,例:PAR1 DW 100,200 PAR2 DW 300,400ADDR_TABLE DW PAR1,PAR2VAR DB 100 DUP(?)DB 2 DUP(0,2 DUP(1,2),3),1 数据定义伪指令,4.2 伪指令,OPER1 DB?,?OPER2 DW?,?MOV OPER1,

15、0;字节指令 MOV OPER2,0;字指令OPER1 DB 1,2OPER2 DW 1234H,5678H MOV AX,OPER1+1 MOV AL,OPER2 类型不匹配 MOV AX,WORD PTR OPER1+1 MOV AL,BYTE PTR OPER2,(AX)=3402H(AL)=34H,1 数据定义伪指令,4.2 伪指令,4.2 伪指令,1)等价伪指令EQU2)等号伪指令=3)定义符号名伪指令LABEL,2 符号定义伪指令,1)等价伪指令EQU格式:符号名 EQ 表达式功能:为常量、表达式及其他各种符号定义一个等价的符号名,但它不申请存储单元。用途:用符号表示常量、数值表达

16、式,即定义符号常量。使用符号常量可使程序简单明了,增强程序的可读性和通用性。EQU与属性运算符TR或THIS联合使用,可以给变量或标号定义新的类型属性并重新命名,但保持其段偏移地址属性不变。利用EQU可以用一个符号名替代一个复杂的地址表达式和其他一些符号,如指令助记符、变量名、标号、段名、寄存器名、宏定义名等。,2 符号定义伪指令等价伪指令EQU,例如:ALPHA EQU 9BETA EQU ALPHA+18BB EQU BP+8,4.2 伪指令,格式:符号名=表达式功能:为常量、表达式及其他各种符号定义一个等价的符号名,并能对所定义的符号多次重复定义,且以最后一次定义的值为准。【例】定义等价

17、符号名。COST=20M=MOVLOST=LOST+10;30LOSTM=ADD;M=ADD,2 符号定义伪指令 等号伪指令=,4.2 伪指令,格式:变量名或标号 LABEL 类型功能:定义与原有变量类型不同的新变量或为指令语句定义有指定类型的标号。通常与数据定义伪指令连用,其功能类似语句“变量名或标号 EQU THIS 类型”。【例】定义新类型的变量。DDBUFLABEL DWORDBUFDB 200 DUP(0)A LABEL FARB:LEADX,BUF,4.2 伪指令,2 符号定义伪指令定义符号名伪指令LABEL,编制一个80X86汇编语言源程序,段是基础,这有两方面含义:一是必须按段

18、来构造程序,二是在程序执行时,要凭借四个段寄存器对各个段的存储单元进行访问。格式:段名 SEGMENT 定位类型 组合类型 类别 段体 段名 ENDS功能:定义一个逻辑段,指定段的名字和范围,段在内存中的起始位置、段与段之间的连接关系。说明:段名由用户指定,开始与结束的段名须一致。SEGMENT/ENDS伪指令把程序分成若干逻辑段。删节号为段体,段体内为指令和伪指令序列。段的长度不超过64KB。SEGMENT后面的参数是可选 项。,4.2 伪指令,3 段定义伪指令SEGMENT/END,假定伪指令主要用于指示汇编程序哪些段是当前段以及这些段与段寄存器之间的对应关系。格式:ASSUME 段寄存器

19、:段名,段寄存器:段名功能:该伪指令告诉汇编程序在汇编时,段寄存器CS、DS、SS和ES应具有的符号段基址,以便汇编指令时确定段和建立错误信息。但是段寄存器实际值(CS除外)还要由传送指令在执行程序时赋值。该伪指令一般出现在代码段中。【例】用ASSUME伪指令建立代码段、堆栈段与CS和SS的对应关系。DATA1SEGMENTADB 1,2,3DATA1ENDSSTACKSEGMENT STACKDB200 DUP(0)STACKENDSDATA2SGEMENTBDB 123ABCDATA2ENDS,4 假定伪指令ASSUME,4.2 伪指令,DATA3SEGMENTCDB?,?,?DATA3E

20、NDSCODESEGMENTASSUMEDS:DATA1,ES:DATA2,CS:CODE,SS:STACKSTART:MOVAX,DATA1MOVDS,AX;DATA1DSMOVAX,DATA3MOVES,AX;DATA3ESQ1:MOVAL,AQ2:MOVC,ALASSUMEDS:DATA2;建立DS与 B段的对应关系,MOVAX,DATA2MOVDS,AX MOVAL,BMOVC,ALCODEENDS ENDSTART,4.2 伪指令,4 假定伪指令ASSUME,5 定位伪指令ORG与地址计数器($),4.2 伪指令,汇编程序在汇编源程序时,每遇到一新段,就为该段设置一个初值为0的汇编地

21、址计数器,汇编程序使用汇编地址计数器保存正在汇编的数据或指令的目标代码在当前段内的偏移地址。当前地址计数器的值可用符号$表示,用户可在程序中直接使用$,表示引用当前汇编地址计数器的值。例如:ARRAY DW 4000H,5000H,6000HCOUNT EQU($-ARRAY)/2 汇编地址计数器的值可以用定位伪指令ORG设置。,格式:ORG 数值表达式功能:将数值表达式的值赋给汇编地址计数器。数值表达式的值须为0-65535之间的非负整数。该伪指令把以下语句定义的内存数据或程序,从表达式指定的起点(偏移地址)开始连续存放,直至遇到新的ORG指令。【例】给汇编地址计数器赋值。DATASEGME

22、NT ORG10;置值为10VAR1DW 100H,200HORG+5;置的值为14+5,即为19VAR2DB 1,2,+1,+2NEQU-VAR2;()=23DATAENDS,5 定位伪指令ORG与地址计数器($),4.2 伪指令,在程序设计中,常把具有某种功能的程序段设计成一个过程。80X86宏汇编语言用于过程定义的伪指令的格式为:过程名 PROC NEAR 或FAR;过程体 过程名 ENDP 其中过程名是过程入口地址的符号表示,它由程序员指定,且开始处和结束处的过程名一致。过程名同标号一样,具有三种属性:段属性、偏移属性和类型属性,类型属性可指定为NEAR或FAR两种。默认时系统约定是N

23、EAR。过程体为过程内的指令和伪指令序列。定义过程是为实现子程序调用而设的,调用格式为:CALL过程名 过程由RET指令返回。,6 过程定义伪指令PROC/ENDP,4.2 伪指令,(1)源程序开始伪指令 在源程序开始处可以用NAME或TITLE为模块取名字。NAME伪指令 格式:NAME 模块名 汇编程序将以给出的“模块名”作为模块的名字。TITLE伪指令 如果程序中没有NAME伪指令,则也可使用TITLE伪指令。格式:TITLE text TITLE伪指令可指定每一页上打印的标题。同时,若程序中没有NAME伪指令,则汇编程序将用text 中的前6个字符作为模块名。text最多可有60个字符

24、。若程序中既无NAME又无TITLE伪指令,则将用源程序名作为模块名。所以NAME及TITLE伪指令并不是必要的,但一般常使用TITLE,以便在列表文件中能打印出标题来。,7 源程序开始和结束伪指令,4.2 伪指令,(2)源程序结束伪指令格式:END 地址表达式 功能:该语句为源程序的最后一个语句,用以标志整个程序的结束,即告诉汇编程序汇编工作到此结束。其中,地址表达式为可选项,若选用地址表达式,则表示此程序是主程序,它可以单独执行,其地址表达式为该程序的启动地址,即程序开始运行的第一条指令的地址,例如,“ENDSTART”,此START是第一条指令的标号;若不选用表达式,则说明此程序为一子程

25、序,不能单独运行,只能被其它程序调用。,7 源程序开始和结束伪指令,4.2 伪指令,4.3 汇编语言程序的结构,一个汇编源程序是分段的,由若干个段形成一个源程序。其中,必不可少的是代码段和堆栈段,堆栈段也可以不用显示定义,可以直接使用隐式堆栈段,如果程序中需要使用数据存储区,还要定义数据段,必要时还要定义附加段。一般情况下,对于不太复杂的程序只需要三个段(即数据段、堆栈段和代码段)就可以了,而对于复杂的程序,除了使用上述三个段以外还可以使用多个段,甚至可以使用多个程序模块。汇编语言源程序结构通常有两种,它们的区别在于代码段中某些部分的编写稍有不同。具体地说,就是用户程序运行结束后,返回DOS的

26、方法上有所不同。,4.3 汇编语言程序的结构,1、用INT 21H返回DOS的程序结构模式 INT 21H是DOS系统功能调用,用这种方法返回DOS的程序结构比较简单,我们编写程序常采用此结构,具体编写时只要在用户程序的最后安排两条指令即可,即:MOV AH,4CHINT 21H2、用过程返回DOS的程序结构模式 采用此种方法返回DOS的程序结构,要求将用户程序定义为一个类型为FAR的过程,在用户程序的开始处要将DS的值压栈,偏移地址0压栈,在程序的最后安排一条RET指令。这样当程序运行到RET指令后便可返回DOS。,4.3 汇编语言程序的结构,4.3 汇编语言程序的结构,4.4 汇编语言程序

27、的开发过程,1.源程序的编辑2.源程序的汇编3.目标文件的链接,4.5 汇编语言程序结构设计,在汇编语言程序设计中,程序有顺序、分支、循环和子程序四种基本结构形式。4.5.1 顺序程序设计4.5.2 分支程序设计4.5.3 循环程序设计4.5.4 子程序的设计4.5.5 宏指令,汇编语言程序设计步骤:(1)分析问题:已知条件、要解决的问题、功能/性能要求等。(2)建立数学模型:把问题数学化、公式化,便于计算机处理。(3)确定算法:简单、速度快、精度高、代码量小、编程容易。(4)绘制程序流程图:用箭头、框图、菱形图等表示程序结构。(5)内存空间分配:为程序或数据分配内存空间。(6)编制程序与静态

28、检查:程序结构层次简单、清楚、易懂。(7)程序调试:利用调试软件DEBUG进行调试。,汇编语言程序设计的特点:(1)算法要分解至指令级;高级语言为语句级。(2)要详细考虑内存空间分配问题:任何一个变量、一条指令都要明确其存储位置。,4.5 汇编语言程序结构设计,顺序程序设计也称为简单程序设计,这种结构的程序不使用分支、循环结构,程序本身的逻辑非常简单,所以只能完成一些简单操作。其特点是程序顺序执行,由前向后逐条执行指令。【例】试编写一程序计算下列表达式的值。=(v-(*+-540)/x式中x、v均为有符号字数据。设、的值存放在字变量、V中,结果存放在双字变量之中,程序的流程图如图所示。,4.5

29、.1 顺序程序设计,4.5.1 顺序程序设计,顺序运算程序流程图,源程序如下:DATASEGMENTXDW200YDW100ZDW3000VDW10000WDW2 DUP(?)DATAENDSSTACKSEGMENT STACK DB 200 DUP(0)STACKENDSCODESEGMENTASSUME DS:DATA,CS:CODE,SS:STACK,START:MOVAX,DATAMOVDS,AX;DATAAXMOVAX,X IMULY;(X)*(Y)DX:AXMOVCX,AXMOVBX,DX;(DX:AX)(BX:CX)MOVAX,ZCWD;(Z)符号扩展ADDCX,AXADCBX,

30、DX;(BX:CX)+(DX:AX)(BX:CX)SUBCX,540,SBBBX,0;(BX:CX)-540(BX:CX)MOVAX,V CWD;(V)符号扩展SUBAX,CXSBBDX,BX;(DX:AX)-(BX:CX)(DX:AX)IDIVX;(DX:AX)/XMOVW,AX;商WMOVW+2,DX;余数DXW+2MOVAH,4CHINT21HCODEENDSENDSTART,4.5.1 顺序程序设计,4.5.2 分支程序设计,分支程序是利用条件转移指令实现程序执行次序改变的一种程序结构形式,即当程序执行到某一指令后,根据某个条件是否满足,分别执行不同的指令序列。一般来说,分支程序经常是

31、先用比较指令或数据操作及位检测指令等来改变标志寄存器各个标志位。然后用条件转移指令进行分支。分支程序结构可以有两种形式,如下图所示,它们分别相当于高级语言中的IF-THEN-ELSE语句和CASE语句。,4.5.2 分支程序设计,【例】编写计算右面函数值的程序:设输入数据为X、输出数据Y,且皆为字节变量。程序流程图如下图所示。,4.5.2 分支程序设计,程序如下:datasegment x db-10 y db?dataendsstacksegment stackdb 200 dup(0)stackendscodesegmentassume ds:data,ss:stack,cs:code,s

32、tart:movax,data movds,ax cmpx,0;与0进行比较 jgea1;x0转a1 movy,-1;x 0时,-1y jmpexita1:jga2;x0转a2 movy,0;x=0时,0y jmpexita2:movy,1;x0,1y exit:movah,4ch int21h code ends endstart,4.5.2 分支程序设计,在实现CASE结构时,可以使用跳转表法使程序能根据不同的条件转移到多个程序分支中去。需要在数据段事先安排一个按顺序排列的转移地址表。输入数字作为偏移量。关键是要理解间接寻址方式JMP指令。【例5.5】设某程序有8路分支,试根据给定的N值(

33、1-8),将程序的执行转移到其中的一路分支。程序流程如图所示。,用跳转表实现多路分支,程序如下:DATASEGMENTTABDW P1,P2,P3,P4,P5,P6,P7,P8NDB 5DATAENDSSTACKSEGMENTDB 200 DUP(0)STACKENDSCODESEGMENTASSUME DS:DATA,SS:STACK,CS:CODE,START:MOVAX,DATAMOVDS,AXMOVAL,NDECALADDAL,ALMOVBL,ALMOVBH,0JMPTABBXP1:JMPEXITP2:JMPEXITP2:JMPEXIT,4.5.2 分支程序设计,P3:JMPEXITP

34、8:EXIT:MOVAH,4CH INT21HCODEENDS END START,上述程序中的无条件转移指令的转移地址采用的是变址寻址。同理,转移地址也可以用寄存器间接寻址或基址加变址寻址。,4.5.2 分支程序设计,4.5.3 循环程序设计,循环结构一般是根据某一条件判断为真或假来确定是否重复执行循环体。循环结构程序缩短了程序的长度、减少了占用的内存空间;但它并不简化程序执行过程,相反,由于增加了一些循环控制等环节,总的程序执行语句和时间会有所增加。循环程序一般由4部分组成:初始化、循环体、循环控制和循环结束处理。循环程序有两种结构形式:DO-WHILE 结构和DO-UNTIL 结构,循环

35、程序各部分的内容:(1)初始化:建立循环次数计数器,设定变量和存放数据的内存地址指针(常用间址方式)的初值等。(2)循环体:实现程序功能的、被重复执行的指令序列。(3)循环控制:修改变量和地址指针,为下一次循环做准备;修改循环计数器或者判断循环条件是否满足,满足则继续循环,否则结束循环。(4)结束处理:它主要用来分析和存放程序的结果。循环控制方式有多种,如计数控制、条件控制等。不管哪一种控制循环方式,最终都是要达到控制循环的目的。若考虑不周,会造成死循环,对这一点要注意。循环可以用跳转语句实现,如JMP,JZ等;也可以用专用循环控制语句实现,如LOOP、LOOPE/LOOPZ、LOOPNE/L

36、OOPNZ。,4.5.3 循环程序设计,【例】求两个多字节数之和。这两个数在10050H地址开始的内存单元中,连续存放,低位在小地址一端,结果放在这两个数之后。设这两个多字节数均为8个字节长。,4.5.3 循环程序设计,编制的程序START:MOVAX,1000H MOVDS,AX;DS1000H MOVSI,50H;第一个数指针SI50H MOVDI,58H;第二个数指针DI58H MOVBX,60H;结果指针BX60H MOVCX,4;循环次数CX4 CLC;清进位CF0AA:MOVAX,SI;取一个字到AX ADCAX,DI;AXAX+DI+CF MOVBX,AX;存一个字到BXPUSH

37、F;保护进位CFADDSI,2;修改第一个数的地址指针SISI+2ADDDI,2;修改第二个数的地址指针DIDI+2ADDBX,2;修改结果指针BXBX+2POPF;恢复标志寄存器LOOPAA;CXCX-1,若CX0转AAHLT;CX0,暂停,例:将首地址为A的字数组从大到小排序(冒泡算法,多重循环)8,5,16,84,32,4.5.3 循环程序设计,多重循环,mov cx,n;元素个数dec cx;比较遍数loop1:mov di,cx;比较次数mov bx,0loop2:mov ax,Abx;相邻两数cmp ax,Abx+2;比较jge continuexchg ax,Abx+2;交换位置

38、mov Abx,axcontinue:add bx,2 loop loop2mov cx,diloop loop1,4.5.4 子程序的设计,从功能上来讲,子程序是主程序的一个组成部分。为了实现程序的结构化、模块化,提高程序的可重用性,通常将主程序中具有公用性、重复性、功能相对独立和完整的一个程序段,单独设计成一个程序模块,供主程序调用,该程序模块就称为子程序。子程序可以实现源程序的模块化,简化源程序结构,提高编程效率。子程序可以嵌套。一定条件下,还可以递归和重入。,4.5.4 子程序的设计,子程序的定义是由过程定义伪指令PROC和ENDP来完成的。其格式如下:过程名 PROC NEAR/FA

39、R 过程名 ENDP子程序调用与返回子程序调用与返回由CALL和RET指令实现。子程序调用方式:近程(段内)调用、远程(段间)调用、直接调用(指令中直接给出调用地址)和间接调用(用寄存器或内存单元给出调用地址)。子程序调用实际是程序的转移,但与转移指令有所不同:子程序调用指令CALL执行时要保存返回地址,每个子程序都有RET指令实现子程序返回。转移指令不考虑返回问题。,1 子程序的定义、调用与返回,F1 PROC.RET;将堆栈中的地;址弹出到CS:IP中F1 ENDP,.CALL F1;将下条指令;的地址压入堆栈.,(1)现场保护与恢复转子前,CPU有关寄存器和内存有关单元是父程序的工作现场

40、,在调用子程序前要设法保护这个现场。例如:subname proc;具有缺省属性的subname过程push ax;保护现场:顺序压入堆栈push bx;ax/bx/cx仅是示例push cx;过程体pop cx;恢复恢复:逆序弹出堆栈pop bxpop axret;过程返回subnameendp;过程结束,4.5.4 子程序的设计,2 子程序设计,(2)参数传递 指主程序与子程序之间相关信息或数据的传递。传递参数需要父程序与子程序默契配合,否则会产生错误结果。入口参数(输入参数):主程序提供给子程序出口参数(输出参数):子程序返回给主程序 参数的形式:数据本身(传值)数据的地址(传址)参数传

41、递方式:寄存器 内存单元 堆栈,4.5.4 子程序的设计,2 子程序设计,例:累加数组ary中的元素,将累加和存入变量sum,数据段 的定义如下:data segment ary dw 1,2,3,4,5,6,7,8,9,10 count dw 10 sum dw?data ends用子程序计算数组元素的累加和入口参数:数组的逻辑地址(传址)元素个数(传值)出口参数:求和结果(传值),4.5.4 子程序的设计,用寄存器传递参数把参数存于约定的寄存器中,可以传值,也可以传址。子程序对带有出口参数的寄存器不能保护和恢复(主程序视具体情况进行保护)子程序对带有入口参数的寄存器可以保护,也可以不保护;

42、但最好一致本例中:入口参数:(CX)元素个数,DS:BX数组的段地址:偏移地址出口参数:(AX)校验和,4.5.4 子程序的设计,code segment assume cs:code,ds:datastart:mov ax,data mov ds,axmov bx,offset ary;BX数组的偏移地址movcx,count;CX数组的元素个数 call proadd;调用求和过程mov sum,ax;处理出口参数 mov ax,4c00h int 21hcode ends end start,proadd proc near xor ax,ax;累加器清0next:add ax,bx;求

43、和 add bx,2;指向下一个字 loop nextretproadd endp,4.5.4 子程序的设计,通过寄存器传递参数,子程序,通过内存单元传送参数主程序和子程序直接采用同一个变量名共享同一个变量,实现参数的传递不同模块间共享时,需要声明本例中:入口参数:count元素个数ary数组名(含段地址:偏移地址)出口参数:sum累加和,4.5.4 子程序的设计,4.5.4 子程序的设计,data segment ary dw 1,2,3,4,5,6,7,8,9,10 count dw 10 sum dw?data endscode segment assume cs:code,ds:dat

44、astart:mov ax,data mov ds,ax call proadd mov ax,4c00h int 21hcode ends end start,proadd proc near push ax push cx push si lea si,ary mov cx,count xor ax,axnext:add ax,si add si,2 loop next mov sum,ax pop si pop cx pop ax retproadd endp,子程序,通过内存单元传送参数,通过堆栈传送参数主程序将子程序的入口参数压入堆栈,子程序从堆栈中取出参数。子程序将出口参数压入堆栈

45、,主程序弹出堆栈取得它们。本例中:入口参数:顺序压入偏移地址和元素个数出口参数:(AX)累加和,4.5.4 子程序的设计,例:累加数组中的元素data segment ary dw 10,20,30,40,50,60,70,80,90,100 count dw 10 sum dw?data endsstack segment dw 100 dup(?)tos label wordstack ends,4.5.4 子程序的设计,通过堆栈传送参数,code1 segmentassume cs:code1,ds:data,ss:stackstart:mov ax,stack mov ss,ax mo

46、v sp,offset tos mov ax,data mov ds,ax mov bx,offset ary push bx mov bx,offset count push bx mov bx,offset sum push bx call far ptr proadd mov ax,4c00h int 21hstart endpcode1 ends,4.5.4 子程序的设计,通过堆栈传送参数,(ip)(cs)sumcountarray,(bp)+0ah,4.5.4 子程序的设计,通过堆栈传送参数,要注意堆栈的分配情况,保证参数存取正确、子程序正确返回,并保持堆栈平衡。主程序实现平衡堆栈:

47、add sp,n 子程序实现平衡堆栈:ret n,4.5.4 子程序的设计,(1)子程序的嵌套 子程序不但可以被主程序调用,而且也可以被其他子程序调用。这种一个子程序调用另一个子程序的情况,称为子程序的嵌套。(2)子程序的递归当子程序直接或间接地嵌套调用自身时称为递归调用,含有递归调用的子程序称为递归子程序。递归子程序一般对应于数学上对函数的递归定义,它往往能设计出效率较高的程序,完成相当复杂的计算,因而是很有用的。递归子程序必须采用寄存器或堆栈传递参数,递归深度受堆栈空间的限制。,3 子程序的嵌套与递归,4.5.4 子程序的设计,3 子程序的嵌套与递归,4.5.4 子程序的设计,在编写汇编语

48、言程序的过程中,有时某个程序段要出现许多次,有时只是参数不同,但功能完全一样,则这样的程序段可以定义成一条指令,称它为宏指令。当程序中遇到这个程序段时,只需用一条宏调用语句,这样有效地缩短了源程序的长度,使源程序易读,也减少了由于重复书写而引起的错误。宏指令的使用要经过如下3个步骤:(1)宏定义:对各个宏指令进行定义,并分别起一个名字;macro_name MACRO 哑元表;形参 LOCAL 标号表;宏定义体 ENDM(2)宏调用:在需要使用的地方,通过宏指令名来调用它;macro_name 实元表;实参(3)宏扩展:由宏汇编程序用宏定义中的指令来代替宏指令名。宏定义体 复制到宏指令位置,实

49、参代形参 LOCAL中的标号?0000?ffff,4.5.5 宏指令,1 宏指令的作用,例题:保存寄存器,4.5.5 宏指令,例题:两个字相乘宏定义:multiply MACRO opr1,opr2,result push dx push ax mov ax,opr1 imul opr2 mov result,ax pop ax pop dx ENDM宏调用:multiply cx,var,xyzbx,4.5.5 宏指令,例题:求绝对值宏定义:absol MACRO oper LOCAL next cmp oper,0 jge next neg opernext:ENDM宏调用:absol v

50、arabsol bx,宏展开:1 cmp var,01 jge?00001 neg var1?0000:1 cmp bx,01 jge?00011 neg bx1?0001:,4.5.5 宏指令,宏的参数 参数的形式灵活多变,可以是常数、变量、存储单元、指令操作码或它们的一部分,也可以是表达式,使用灵活多变的参数,同一个宏定义甚至可以执行不同的操作。几个宏操作符:替换操作符:用于将参数与其他字符分开。用在宏体 中。如果参数紧接在其他字符之前或之后,或者参数 出现在带引号的字符串中,就必须使用该伪操作符。:字符串传递操作符:用在宏调用的实参中。在宏调用 中,如果传递的字符串实参数含有逗号、空格等

展开阅读全文
相关资源
猜你喜欢
相关搜索
资源标签

当前位置:首页 > 建筑/施工/环境 > 农业报告


备案号:宁ICP备20000045号-2

经营许可证:宁B2-20210002

宁公网安备 64010402000987号