微机原理第4章汇编语言程序设计课件.ppt
第4章 汇编语言程序设计,4.1 汇编语言语法4.2 汇编语言程序实现4.3 汇编语言程序设计方法及应用4.4 汇编语言程序设计举例,微机原理,4.1 汇编语言语法,【例题4.1】实现:123+456sum 的源程序,CODESEGMENT;语句6 ASSUME CS:CODE,DS:DATAMAIN PROC FAR;语句8START:PUSH DS;语句9.;RET;语句17MAIN ENDP;语句18CODE ENDS;语句19,数据段,代码段,DATA SEGMENT;语句1 A DW 123;语句2 B DW 456;语句3 SUM DW?;语句4DATA ENDS;语句5,END START;语句20,名字 指令/伪指令 操作数1,操作数2,段=语句,1.源程序组成,源程序=段,段:数据段、堆栈段、附加段、码段,语句:指令性语句,由CPU执行,如:语句8语句17。指示性语句,指示汇编,如语句1、5、6、19、20。,名字:段 名,如:DATA、CODE 变量名,如:A、B、SUM 过程名,如:MAIN 标号名,如:START,汇编程序构成 暨 本章主要内容,指令性语句本章涉及各色运算符,用以与数据配合构成操作数指示性语句几种起定义作用的伪指令数据定义伪指令符号定义伪指令段定义伪指令,1)组成名字的合法字符有:字母(不分大小写);数字09;特殊符号(“?”,“:”,“”,“_”,“$”)。2)名字的有效长度小于31个西文字符。3)名字以字母开头。4)不能把保留字用作名字。,2.名字命名规则,3.名字属性,(1)变量名,(2)段名:该段起始位置的段地址值,段属性:变量所代表的数据区所在段的 段基址;偏移量:变量所代表的数据区首字节所 在段内偏移地址;类 型:BYTE、WORD、DWORD、DQ、DT长 度:变量所代表的数据区中数据元 素的个数。规 模:变量所代表的数据区中数据所 占空间大小,以字节计。,(3)过程名或标号名,(4)常量名:代表一常数,段属性:过程起始位置或标号处 段地址值偏移量:过程起始位置或标号处 偏移地址值类 型:NEAR、FAR,用于程序跳转,4.1.2 汇编语言伪指令,1.数据定义伪指令 变量名 数据定义伪指令 操作数1,操作数2,DB、DD、DW、DQ、DT,字节、字、双字、4字、5字的变量。,(1)数字常量:十进制、八进制、十六进制、二进制等,缺省形式是十进制;(2)字符常量,用单引号括起来,被存储的是该字符的ASCII码;(3)符号常量,必须是预先已定义的符号;(4)符号“?”,表示预留空间,内容不定;(5)DUP,表示内容重复的数据。具体形式为:次数 DUP(被重复的内容),操作数:,【例】D_A DB 10,A,BC D_B DW 1234H D_C DQ 5678H,D_A 10 41H 42H 43H D_B 34H 12H D_C 78H 56H 0 0 0 0 0D_C+7 0,(1)DB定义的数据,每个数据元素占据1个存储单元;DW定义的数据,每个数据元素占据2个存储单元;(2)字数据存储时,低字节存储在低地址单元中,高字节存储在高地址单元中;(3)字符被存放时为它的ASCII码,例 A的ASCII码为41H;(4)符号地址具有以下关系:D_B=D_A+3 D_D=D_B+2=D_A+6,注:,ORG 100HD_E DB 3 DUP(?)EVEND_F DW D_ED_G DB 2 DUP(1,3,4)D_H DW$+2,变量 内容 偏移地址D_E?100?101?102 103 00H 104D_F 01H 105D_G 1 106 3 107 4 108 1 109 3 10A 4 10BD_H 0CH 10C 01H 10D,下一个存储位置从偶地址开始,己定义变量,取该变量偏 移地址,代表当前偏移地址,2.符号定义伪指令,(1)EQU 格式:名字 EQU 表达式,例:VB EQU 641024;VB代表数值表达式的值 A EQU 7 B EQU A2,注意:1.如果表达式中有变量,应在该语句前给出该变量的定义;2.EQU语句不能给某一变量重复定义;3.VB、A、B不占用内存,(2)等号=,格式:名字=表达式,功能:与EQU基本相同,区别是它可以对同一个 名字重新定义。例:COUNT=10 MOV AL,COUNT;COUNT=5;可重复定义,(3)LABEL,格式:变量/标号 LABEL 类型,功能:定义变量或标号的类型,而变量或标号的段属性和偏移属性由该语句所处的位置确定。,变量的类型有:BYTE、WORD、DWORD、DQ、DT;标号的类型有:NEAR、FAR。,【例】利用LABEL使同一个数据区有一个以上的类型及相关属性。AREAW LABEL WORD;AREAW与AREAB指向相同的数 据区,AREAW类型为字,而 AREAB类型为字节AREAB DB 100 DUP(?)MOV AX,1234HMOV AREAW,AX;(AREAW)=1234HMOV BL,AREAB;BL=34H,3.段定义伪指令,段名 SEGMENT 定位类型 组合类型 类别 段名 ENDS,BYTE:B,即段可以从任何地址开始;WORD:0B,即段的起始地址必须为偶地址;PARA:0000B,即段从节(PARAGRAPH)边界开始,每16个字节 为1小段,所以,其起始地址必为16的倍数。PAGE:0000 0000B,即段从页边界开始,每256个字节为1页,所 以,其起始地址必为256的倍数。,定位类型:说明段的起始地址应有怎样的边界值:,组合类型:说明程序连接时的段合并方法,1 PUBLEC:将同类别名段组装在一起形成一个逻 辑段;2 STACK:与PUBLIC一样,只用于堆栈段。在汇 编及连接后,系统自动为SS及SP分配 值,在可执行程序中,SP初值指向栈底。3 COMMON:同名段从同一个内存地址开始装入。所以,各个逻辑段将发生覆盖。连接 以后,该段长度取决于同名段中最长 的那个,而内容有效的是最后装入的 那个。,4 MEMORY:与PUBLIC同义,只不过MEMORY定义的 段装在所有同名段的最后。若连接时 出现多个MEMORY,则最先遇到的段按 组合类型MEMORY处理,其他段组合类 型按PUBLIC处理。5 PRIVATE:不组合,该段与其它段逻辑上不发 生关系,即使同名,各段拥有各自 的段基值。缺省值6 AT exp:段地址为表达式exp的值(长度为16位)。此项不能用于代码段。,当几个程序模块进行连接时,其中具有相同类别名的段,按出现的先后顺序被装入连续的内存区。没有类别名的段,与其它无类别名的段一起连续装入内存。,类别:类别的作用是在连接时决定各逻辑段的装入顺序。类别名必须用单引号括起来。,ASSUME 段寄存器名:段名,段寄存器名:段名,ASSUME:用于明确段与段寄存器的关系,说明:该伪指令出现在码段中;本伪指令只是指示各逻辑段使用段寄存器的情况,并没有对段寄存器的内容进行赋值。DS、ES的值必须在程序段中用指令语句进行赋值,而CS、SS由系统负责设置,程序中也可对SS 进行赋值,但不允许对CS赋值。,例:ASSUME DS:DSEG,CS:CSEG,ES:ESEG,SS:SESG,例:ASSUME CS:CODE,DS:DATA,ES:DATA,【例】按下面要求,写出程序框架,数据段从0E000H开始,其中有100字节的数组,其类型属性既是字又是字节;2.堆栈段从小段开始,段组名为STACK;3.代码段中指定段寄存器,主程序从1000H开始,给有关段寄存器赋值;4.程序结束。,DSEG SEGMENT AT 0E000H D_BYTE DB 100 DUP(?)D_WORD EQU WORD PTR D_BYTEDSEG ENDSSSEG SEGMENT PARA STACK DB 200 DUP(?)SSEG ENDSCSEG SEGMENT ORG 1000H ASSUME CS:CSEG,DS:DSEG,SS:SSEG,MAIN PROC FAR XOR AX,AX PUSH AX PUSH DS MOV AX,DSEG MOV DS,AX RET MAIN ENDPCSEG ENDS END MAIN,4.1.3 汇编语句,语句格式:名字 操作 操作数;注释,常量、变量和表达式组成,由常量、变量和运算符组成,1.算术运算符,例(1)ARRAY DW 1*2+3-4,56H MOV AX,ARRAY;汇编后为:MOV AX,1(2)MOV AL,7FH MOD 2;汇编后为:MOV AL,1(3)MOV AH,15/4;汇编后为:MOV AH,3,2.逻辑运算符,例1:MOV AH,11110000BMOV AL,NOT AH;MOV AL,00001111BMOV BL,AH OR AL;MOV BL,11111111BMOV BH,AH XOR AL;MOV BH,11111111B,例2:从端口86H读取一个字节,高位屏蔽后从端口6送出。PORT EQU 86H IN AL,PORT AND1 AL,0FH;AND1为逻辑指令 MOV DX,PORT AND2 0FH;AND2为汇编运算符 OUT DX,AL,3.关系运算符,关系运算符两边的操作数必须是两个数值或同一段中两个存储单元地址,运算结果应为逻辑值,结果为真,表示为0FFFFH;结果为假,则表示为0。,例:A EQU 80H B EQU 88H MOV AL,A EQ B MOV AH,A NE B MOV BL,A LT B MOV BH,A GT B MOV CL,A LE B MOV CH,A GE B,4.分析/数值返回运算符,SEG 变量或标号,返回变量或标号的段地址,OFFSET 变量或标号,返回变量或标号的偏移量,TYPE 变量或标号,LENGTH 变量,SIZE 变量,返回变量或标号的类型值,返回DUP定义的数据占据的单元数;非DUP定义的数据,返回1。,返回DUP定义的数据占据的字节数;非DUP定义的数据,返回类型值。,变量类型值:DB:1,DW:2,DD:4,DQ:8,DT:10。标号类型值:NEAR:-1,FAR:-2。,【例】数据定义如下:DATA SEGMENT AT 2000H BUF1 DB 0,1,2,3,4,5,6,7,8,9 BUF2 DW 5 DUP(0)DATA ENDS则:SEG BUF1=2000H SEG BUF2=2000HOFFSET BUF1=0000H OFFSET BUF2=000AHTYPE BUF1=1 TYPE BUF2=2LENGTH BUF1=1 LENGTH BUF2=5SIZE BUF1=1 SIZE BUF2=10,5.汇编运算符(PTR),类型 PTR 变量/标号,典型应用之一:重新指定变量类型 例:数据定义如下:BUFW DW 1234H,5678H 则下列指令合法:MOV AX,BUFW;临时改变BUFW的字属性为字节属性 MOV AL,BYTE PTR BUFW,典型应用之二:指定内存操作数的类型例:INC BX;汇编将指示出错 INC BYTE PTR BX;正确 INC WORD PTR BXSI;正确,分析:在寄存器间接寻址、寄存器相对寻址、基址变址寻址或相对基址变址寻址等内存寻址方式中,往往很难判断出操作数的类型属性,应对操作数类型加以说明。,典型应用之三:与EQU一起定义一个新的变量 变量或标号 EQU 类型 PTR,例:BUFW DW 1234H,5678H BUFB EQU BYTE PTR BUFW;BUFB的类型 属性为字节,其它属性与BUFW一样。MOV AX,BUFW;AX=1234HMOV AL,BUFB;AL=34H,6.汇编运算符(THIS),格式:THIS 类型 可以像PTR一样建立一个指定类型的地址操作数,该操作数的段地址和偏移地址与下一个存储单元地址相同。,例:BUFBEQU THIS BYTEBUFW DW 1234H,5678H.MOV AX,BUFW;AX=1234HMOV BL,BUFB;BL=34H,BUFB的偏移地址和BUFW完全相同,但它是字节类型;而BUFW则是字类型。,程序组织结构,data segment;定义数据段 data ends;-extra segment;定义附加段 extra ends;-code segment;定义代码段 assume cs:code,ds:data,es:extrastart:mov ax,data mov ds,ax;段地址 段寄存器 code ends end start,DSES,SS,CS,EXE程序的内存映象图,装入模块,文件头,4.2 汇编语言程序实现,开发过程1:源程序的编辑,源程序文件要以ASM为扩展名源程序文件的形成(编辑)可以通过任何一个文本编辑器实现:DOS中的全屏幕文本编辑器EDIT其他程序开发工具中的编辑环境MASM程序员工作平台PWB中的编辑环境EDIT lt301a.asm,开发过程2:源程序的汇编,汇编是将源程序翻译成由机器代码组成的目标模块文件的过程MASM 6.x提供的汇编程序是ML.EXE:ML/c lt301a.asm如果源程序中没有语法错误,MASM将自动生成一个目标模块文件(lt301a.obj);否则MASM将给出相应的错误信息这时应根据错误信息,重新编辑修改源程序后,再进行汇编,开发过程3:目标模块的连接,连接程序能把一个或多个目标文件和库文件合成一个可执行程序(.EXE、.COM文件):LINK lt301a.obj如果没有严重错误,LINK将生成一个可执行文件(lt301a.exe);否则将提示相应的错误信息这时需要根据错误信息重新修改源程序后再汇编、链接,直到生成可执行文件,汇编和连接的依次自动实现,ML汇编程序可自动调用LINK连接程序,实现汇编和连接的依次进行ML lt301a.asm汇编程序ML.EXE可带其他参数,常用ML/Fl/Sg lt301a.asm该命令除产生模块文件lt301a.obj和可执行文件lt301a.exe外,还将生成列表文件lt301a.lst列表文件是一种文本文件,含有源程序和目标代码,对我们学习汇编语言程序设计和发现错误很有用。采用/Sg选项,将在列表文件中得到有些伪指令相应的硬指令,开发过程4:可执行程序的调试,经汇编、连接生成的可执行程序在操作系统下只要输入文件名就可以运行:lt301a操作系统装载该文件进入主存,并开始运行如果出现运行错误,可以从源程序开始排错,也可以利用调试程序帮助发现错误采用DEBUG.EXE调试程序:DEBUG lt301a.exe,Debug与程序调试,前面完成的简单程序示例,但並不是意味编程结束,最重要的是要來看看*.COM 或*.exe加载到内存是怎樣的情形,这也是将来写复杂程序时调试的必要的步驟。最简单的调试工具就是 DOS/Windows 所附的 DEBUG.EXE(Windows 9x 的 DEBUG.EXE 在 C:WINDOWSCOMMAND 子目录内,NT/2000在C:winntsystem32目录,也可拷贝到汇编工作目录使用 H:MASM50)。使用 DEBUG 加载要调试的程序用法如下:(蓝色的字是你必须输入的,记得每次要按 Enter 鍵)H:MASM50.masm50debug Enter就是 DEBUG 后面接上“要调试的程序名”即可,如果程序带有参数,就直接接在“程序名”后面即可。DEBUG 的每個命令都用一个英文字母表示,进入 DEBUG 状态后你会看到屏幕上有一-,表示 DEBUG 已经准备好,等你输入调试参数。,汇编程序返回DOS方法,1.标准方法 MAIN PROC FAR PUSH DS MOV AX,0 PUSH AX RET MAIN ENDP,2.DOS功能调用方法 MOV AH,4CH INT 21H,程序组织结构,data segment;定义数据段 data ends;-extra segment;定义附加段 extra ends;-code segment;定义代码段 assume cs:code,ds:data,es:extrastart:mov ax,data mov ds,ax;段地址 段寄存器 code ends end start,DSES,SS,CS,EXE程序的内存映象图,装入模块,文件头,code segmentmain proc far assume start:push ds mov ax,0 push ax retmain endpcode ends end start,code segmentmain proc far assume start:mov ax,4c00h int 21hmain endpcode ends end start,代码设计返回DOS方法,4.3 汇编语言程序设计方法及应用,(1)分析问题 包括找出已知条件、问题特点、问题中的规律并归纳出数学模型。注意:有些问题不一定非要写出数学模型,或者根本写不出数学模型。但是,当有了一个数学模型之后,就可使用很多行之有效的计算方法。(2)确定算法 指根据人们在解决实际问题时的逻辑思维中的常规推理,去找算法。如果已有数学模型,可以直接或间接利用一些现有的计算方法。,1.程序设计步骤,4.3.1 概述,(3)绘制流程图,采用流程图:(1)使解题思路清淅,有利于理解和编制程序;(2)有利于修改程序和减少错误等;(3)对于一个复杂的问题,可以画多级流程图,先画出粗框图,再逐步求精,画出细框图。,流程图是程序算法的图形描述,即用图形的方式把解决问题的先后次序和程序的逻辑结构直观地、形象地描述出来;,(4)分配存储空间及工作单元(包括寄存器),8088/8086存储器结构要求存储空间分段使用。因此,数据段、堆栈段、代码段以及附加段要按需要分别定义。工作单元即可以设置在数据段或附加段中的某些存储单元,也可以设置在CPU内部的数据寄存器中。,根据流程图和确定的算法逐条语句地编写程序,注意不同的机器有不同的指令系统。,(5)编写程序,(6)静态检查,看程序是否具有所要求的功能;程序是否清晰易读;选用指令是否合适;程序语法和格式上是否有错;指令中引用的符号、标号和变量是否定义正确;程序执行流程是否符合算法和流程图等等;适当考虑字节数要少,执行速度要快等。,(7)运行调试,静态检查可以发现一些问题,但毕竟还受到个人主观因素的影响。只有在机上运行通过并且结论正确的程序,才是正确的程序。事实上,即使一个非常有经验的程序员,也不能说程序一编就成功,特别是一些复杂的程序,必须经过调试、修改、再调试、再修改,反复多次之后,才能得到一个比较满意的程序。,【例】编程实现在100个无符号字节整数的数组中找出最大数。,(1)分析问题 本例中,有100个整数的数组,可以把它看作一个集合,记作S。在此集合中找出最大数,记为maxS。(2)确定解决问题的算法 人工方法:首先从第一个数据开始,一边看一边比较两个数的大小,看到较大数就记下,将较小数丢掉;再将此较大数与下一个数进行比较,始终将比较大的数记下,一直将数组中的数两两比较完毕,就能找到最大数。,首先,建立一个数据指针指向数据区的首地址,将第一个数取到某个寄存器中(例AL),与下一个数相比较,若下一个数大,就将它存到AL中,替换掉原来的数;然后调整数据指针,将AL的数与此指针所指的数进行比较,再重复上述步骤,两两比较下去,直到比较完毕,结果AL中留下最大数。,(3)算法、流程图,Y,N,N,Y,(4)存储设计及数据定义,把数组存放在数据段中,并设置50个字节堆栈空间。利用BX寄存器作数据指针,用CX作计数器,用AL暂存较大数。,DSEG SEGMENT;定义数据段 ARRAY DB X1,X2 COUNT DW$-ARRAY;计算数据个数DSEG ENDSSSEG SEGMENT PARA STACK STACK;定义堆栈段 SDAT DB 50 DUP(?)TOP EQU LENGTH SDATSSEG ENDS,CSEG SEGMENT;定义代码段 ASSUME CS:CSEG,DS:DSEG,SS:SSEG MAIN PROC FAR;定义过程 START:PUSH DS;为返回DOS作准备 MOV AX,0 PUSH AX MOV AX,DSEG MOV DS,AX;设置DS MOV AX,SSEG MOV SS,AX;设置SS MOV AX,TOP MOV SP,AX;设置SP初值 MOV BX,OFFSET ARRAY;设置数据区指针首地址,MOV CX,COUNT;设置计数器初值 DEC CX;设置比较次数 MOV AL,BX;取数入ALAGAIN:INC BX;指向数据区下一个数据 CMP AL,BX;两数比较 JAE NEXT;ALBX,转NEXT MOV AL,BX;否则,把较大数取入AL NEXT:DEC CX;全部数据比较完否?JNZ AGAIN;否,转AGAIN RET;全部比较完毕,返回DOS MAIN ENDP CSEG ENDS END START,4.3.2 典型程序结构,A,测试条件?,Y,N,Y,N,顺序结构,分支结构,循环结构,4.3.3 分支程序设计,a.双分支情况之一,b.双分支情况之二,分支程序结构:,条件1,分支程序1,分支程序n,分支程序2,条件2,条件n,判定条件,分支程序1,分支程序n,分支程序2,c.多分支情况之一,d.多分支情况之二,条件1,条件2,条件n,Y,Y,Y,N,N,程序段1,条件测试,分支1,分支2,Y,N,S2,BRANCH,图 4.11 双分支程序组成,【例4.4】比较两个无符号数,把大数存入MAX单元。,取第一个数X1,MAXX1,MAXX2,开 始,结 束,X1-X20?,Y,N,CSEG SEGMENT ASSUME CS:CSEG,DS:DSEG START:MOV AX,DSEG;给数据段地址附值 MOV DS,AX MOV AL,NUMBER;取第一个数X1 CMP AL,NUMBER+1;与第二个数X2 JNC BRANCH;若X1 X2,转BRANCH MOV AL,NUMBER+1;否则,第二个数BRANCH:MOV MAX,AL;保存较大数 MOV AH,4CH INT 21HCSEG ENDS,DSEG SEGMENT NUMBER DB X1,X2;X1和X2为二个无符号数 MAX DB?DSEG ENDS,数据定义,码 段,END START;汇编结束,多分支结构程序设计,利用计算机解决实际问题时,常遇到这样的情况:处理某个问题时有多种选择方案,根据实际情况选择其中一种。每种处理方案由一段程序完成,每一段程序可以看作一个分支,程序在执行过程中根据当前的状况,决定下一步应执行哪一个分支,这就构成了多个分支的程序。如用计算机控制一台电动机,该电动机有正转、逆转,在每种转动方式下又有几种转速的档次控制,这些控制可以通过键盘09的数字键进行选择,进入某种档次选择后,执行相应分支程序,使电机以最佳方式由一个状态进入所选状态。假设程序的十个分支的起始地址分别为ADR0,ADR1,.ADR9。,1:;*EXAM 6.5.1*2:SSEGSEGMENTSTACK3:STKDB20 DUP(0)4:SSEGENDS5:DSEGSEGMENT6:DSEGENDS7:CSEGSEGMENT8:ASSUMECS:CSEG,DS:DSEG9:ASSUMESS:SSEG10:MOTOR:MOVAX,DSEG11:MOVDS,AX12:MOVAX,SSEG13:MOVSS,AX14:MOVSP,SIZE STK15:MOVAH,01 16:INT21H17:CMPAL,0 18:JZADR0 19:CMPAL,1 20:JZADR1 21:22:CMPAL,823:JZADR824:ADR9:25:ADR0:ADR1:ADR8:CSEGENDS:ENDMOTOR,多分支结构程序设计,多分支结构程序设计,地址常数表法 所谓地址常数表法,就是把多个分支中的每个分支程序段的起始地址顺序存放在一个存储区中,这个存储区称地址表存储区。根据键值,将相应处理程序的入口地址取入某寄存器,然后用间接转移指令实现转移。,1:;*EXAM 6.5.2*2:SSEGSEGMENTSTACK3:STKDB20 DUP(0)4:SSEGENDS5:DSEGSEGMENT6:ADRTABDWOFFSET ADR0,OFFSET ADR17:DWOFFSET ADR2,.,OFFSET ADR98:DSEGENDS9:CSEGSEGMENT10:ASSUMECS:CSEG,DS:DSEG11:ASSUMESS:SSEG12:BRANCH:MOVAX,DSEG13:MOVDS,AX14:MOVAX,SSEG15:MOVSS,AX16:MOVSP,LENGTH STK,多分支结构程序设计,17:LEADI,ADRTAB;取地址表首址18:MOVAH,01;读键盘19:INT21H20:SUBAL,0;转换为数字21:XORAH,AH;扩展为字数据22:SHLAX,1;乘223:ADDDI,AX;形成相应地址24:MOVAX,DI;取程序入口25:JMPAX;转去执行 26:ADR0:27:ADR1:ADR9:CSEGENDS:ENDBRANCH,MOV BX,AXJMP ADRTABBXMOV BX,AXJMP DI+BX,多分支结构程序设计,4.3.4循环结构程序设计,(1)初始化部分这是循环的准备部分,为程序操作、地址指针、循环计数、结束条件等设置初始值。(2)循环体,包括以下3个部分:循环工作部分-这是循环程序的主体,完成程序的基本操作,循环多少次,这部分语句就执行多少次。循环修改部分-修改循环工作部分的变量地址等,这保证每次重复时,参加执行的数据能发生有规律的变化。循环控制部分-保证循环条件满足时进入循环;循环结束条件不满足时,退出循环,执行循环体外的后续语句。(3)循环结束部分 完成循环结束后的处理,如数据分析、结果的存放等。,循环程序典型结构,【例4.8】统计字符串STRING中空格的个数。,数据定义为:,DSEG SEGMENT STRING DB Where there is a will,DB there is a way.$RESULT DW?DSEG ENDS,被统计的字符串,开设结果存放单元,CSEG SEGMENT ASSUME DS:DSEG,CS:CSEG START:MOV AX,DATA MOV DS,AX,给数据段段地址附值,取数,空格?,累计计数器加1,修改地址指针,结束符?,MOV BX,OFFSET STRING MOV DX,0NEXT:MOV AL,BX CMP AL,$JZ FIN CMP AL,20H JNZ CONT INC DXCONT:INC BX JMP NEXT FIN:MOV RESULT,DX MOV AH,4CH INT 21H CSEG ENDS END START,初 始 化,保存结果,结 束,Y,N,Y,N,循环程序控制方法之一-计数法循环次数已知,1.正计数法,2.负计数法,计数器的初值为0,每执行一遍循环,计数器加1,然后与规定的循环次数比较,若相等,则结束循环,否则继续循环。,计数器的初值为循环次数,每执行一遍循环体后,计数器减1,当减为0时,结束循环,否则继续循环。,【例4.9】分别统计COUNT个数据中正、负数的个数。,DATA SEGMENT BUF DB-32,25,36,-18,-64,0,-3 COUNT EQU$-BUF PLUS DB?MINUS DB?DATA ENDS,数据定义如下:,正计数法,负计数法,循环程序控制方法之二-条件控制,当只知道进入或结束循环的条件,而无法知道循环次数时,可采用条件控制法。,1.精度:对于数值求解问题,有时无法得到精确解。通常的方法是,在迭代计算过程中,把本次迭代结果与前一次迭代结果相比,当符合精度要求时,结束迭代循环。,2.设置结束标志:在数组和表格处理问题中,在数据表格末尾设置一结束标志,作为循环结束条件。,循环程序控制方法之三-逻辑尺,【例4.10】设在数据组X和Y中各存在有10个数据元素。试编写程序计算:Z1=X1+Y1、Z2=X2+Y2、Z3=X3-Y3、Z4=X4-T4、Z5=X5-Y5 Z6=X6+Y6、Z7=X7-Y7、Z8=X8-Y8、Z9=X9+Y9、Z10=X10+Y10并把结果存入数组Z中。,数据定义:,DSEG SEGMENT X DW X1,X2,X3,X4,X5,X6,X7,X8,X9,X10 Y DW Y1,Y2,Y3,Y4,Y5,Y6,Y7,Y8,Y9,Y10 Z DW 10 DUP(?)LR DW 0000 0000 1101 1100B DSEG ENDS,X1+Y1,X3-Y3,逻辑尺,Y,N,4.3.5 子程序设计,一、过程定义、过程调用,过程名 PROC 类型 RET 过程名 ENDP,1.定义,2.调 用,CALL 过程名,N E A R 子程序书写形式,CODE SEGMENT ASSUME MAIN PROC FAR CALL SUB1 RET SUB1 PROC NEAR CALL SUB2 RET SUB2 PROC NEAR RET SUB2 ENDP SUB1 ENDP MAIN ENDPCODE ENDS,调 用 图 示,CALL SUB1,CALL SUB2RET,RET,主程序,子程序SUB1,子程序SUB2,F A R 子程序书写形式,CODE1 SEGMENT ASSUME MAIN PROC FAR CALL SUB RET MAIN ENDPCODE1 ENDSCODE2SEGMENT ASSUME SUB PROC FAR RET SUB ENDPCODE2 ENDS,CALL指令-段内调用,直接寻址,间接寻址,CALL proc-name,CALL disp16,IP入栈;IP IP+偏移量,例:CALL SUB1,寻址方式,格 式,操 作,注:段内调用,CS不变,CALL r16/m16,IP入栈;IP(r16)/(m16),例:CALL BX CALL WORD PTR BX,CALL指令-段间调用,直接寻址,间接寻址,CALL FAR proc-name,CS入栈;IP入栈;CS 过程的段地址;IP 过程的偏移地址。,例:CALL SUB1,寻址方式,格 式,操 作,注:DWORD PTR表明内存操作数属性为双字,用于段间调用,CALL mem32,CS入栈;IP入栈;IP(EA+1,EA)CS(EA+3,EA+2),例:CALL DWORD PTR BX,远过程名,RET 指令,段内:,RET,RET exp,IP出栈,IP出栈 SP SP+exp,段间:,RET,RET exp,IP出栈 CS出栈,IP出栈 CS出栈 SP SP+exp,返回类型,格 式,操 作,注:返回类型由调用类型定,子程序参数传递,方法一:寄存器方法二:内存方法三:堆栈,参数:,入口参数,出口参数,在子程序中被处理的数据,表示子程序处理结果的数据,软延时:指利用CPU执行指令需要耗费一定时间的特点实施的延时,常用减1循环来实现。,例:8088CPU,主频4.77M,每个时钟周期为:1/4.77M=0.21s。循环指令LOOP,当CX不为零时,执行循环转移分支,占用17个时钟周期;当CX为零时,退出循环,占用5个时钟周期。如果CX初值是2801时,执行指令WAIT1:LOOP WAIT1,所需时间为:,(0.212801)17+0.21 5 10ms,10ms延时子程序,;子程序:DELAY;功能:实现软件延时,延时单位时间为10ms;入口参数:BX,延时常数,实际延时时间为:10*BX(ms);出口参数:无,DELAY PROC NEAR PUSH BX;现场保护 PUSH CXWAIT0:MOV CX,2801;内循环次数,大小由单位时间定WAIT1:LOOP WAIT1;延时10ms DEC BX JNZ WAIT0 POP CX POP BX RETDELAY ENDP,子程序说明,子程序调用,实现100ms、550延时,CSEG SEGMENT ASSUME CS:CSEG,MAIN PROC FAR PUSH DS SUB AX,AX PUSH AX MOV BX,10;延时100ms,参数赋值 CALL DELAY;调用延时子程序 MOV BX,55;延时550ms,参数赋值 CALL DELAY;调用延时子程序 RET MAIN ENDP,4.3.6 宏,宏是源程序中一段有独立功能的程序代码。定义一次,便可以多次反复调用,宏定义格式,宏指令名 MACRO 形式参数表.ENDM,宏指令体,【例4.15】完成2个压缩BCD数加法的宏定义,DECADD MACRO OP1,OP2 MOV AL,OP1 ADD AL,OP2 DAA MOV OPR1,AL ENDM,宏调用格式,宏指令名 实参数表,给出了宏调用中要用到的参数,实参数之间用逗号隔开;实参数和形式参数的顺序一致。原则上,实参数的个数应和形式参数个数相等,但汇编程序允许它们不等。,例:,DECADD DL,BUFFERDECADD AREA1,AREA2,宏展开:指宏定义体替换宏指令名,并用实参数替换形式参数。,DECADD DL,BUFFER扩展成:+MOV AL,DL+ADD AL,BUFFER+DAA+MOV DL,AL,注:当宏调用中实参数个数和形式参数个数不等时,若实参数个数大于形式参数个数,在替换时多余的实参数不予考虑。若实参数个数小于形式参数个数,则多余的形式参数作为空(字符)或零(数字)处理。,加号表示该语句由宏展开得到。,宏与子程序,(1)宏 由宏汇编程序MASM在汇编过程中进行处理,在每个宏调用处,将相应的宏定义体插入;子程序 调用指令CALL和返回指令RET则是CPU指令。执行CALL指令时,程序被控制转移到子程序的入口地址处。(2)宏指令 简化源程序,但不能简化目标程序,汇编以后,在宏定义处不产生机器代码。但在每个宏调用处,通过宏扩展,在目标程序中插入与重复次数一样的目标代码。因此不节省内存。子程序 在目标程序中定义子程序的地方将产生相应的机器代码,但每次调用时,只需用CALL指令,不再重复出现子程序的机器代码,一般来说可以节省内存单元。,4.3.7 系统功能调用,PC-DOS系统中设置两层内部子程序供用户使用,即DOS功能模块和基本输入输出子程序BIOS。,1.DOS功能调用 DOS共提供了近80个功能调用,大致分为:设备管理、文件管理和目录管理等几类。一般,调用系统功能时总是先采用DOS层功能模块,如果这层模块内容达不到要求,再进一步调用BIOS层的子程序。DOS通过INT 21H为程序员提供一系列的功能调用,并作为应用编程接口。,DOS功能调用方法,(1)根据需要的功能调用设置入口参数。(2)把功能调用号送AH寄存器。(3)发软中断指令“INT 21H”。(4)可根据有关功能调用的说明取得出口参数。,DOS功能调用INT 21H基本功能:,2.BIOS功能调用方法,BIOS常驻ROM,独立于DOS,可与任何操作系统一起工作。它的主要功能是驱动系统所配置的外部设备,如磁盘驱动器、显示器、打印机及异步通讯接口等。通过INT 10HINT 1AH向用户提供服务程序的入口,使用户无需对硬件有深入了解,就可完成对I/O设备的控制与操作。BIOS的中断调用与DOS功能调用类似。,BIOS功能调用 INT 16H基本功能:,BIOS功能调用INT 10H基本功能:,4.4 汇编语言程序设计举例,【例4.16】将5位ASCII码表示的十进制数(注:不