汇编语言程序设计ok.ppt_第1页
汇编语言程序设计ok.ppt_第2页
汇编语言程序设计ok.ppt_第3页
汇编语言程序设计ok.ppt_第4页
汇编语言程序设计ok.ppt_第5页
已阅读5页,还剩97页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

微机原理与接口技术,第4章 汇编语言程序设计,本章内容,汇编语言源程序:用汇编语言编写的程序,或简称为源程序。 汇编程序:将源程序翻译成机器语言的程序 目标程序:机器语言代码程序 连接程序:将库文件和目标文件连接在一起形成可执行文件的程序 目前常用的汇编程序有宏汇编MASM 汇编语言程序从建立到汇编、连接形成可执行程序的整个过程如图所示:,4.1 汇编语言程序格式,4.1 汇编语言程序格式,汇编源程序:,4.1 汇编语言程序格式,三、一般汇编语言程序的结构形式 NAME1 SEGMENT ;段的起始 语句1 ; 语句2 ; 语句n ; NAME1 ENDS ;段的结束 NAME2 SEGMENT ;段的起始 语句1 ; 语句2 ; 语句m ; NAME2 ENDS ;段的结束 END ;源程序结束,m条语句序列构成的语句体,n条语句序列构成的语句体,4.1 汇编语言程序格式,8086 汇编语言语句的分类 指令语句 伪指令语句 宏指令语句,4.2 汇编语言基本语法,4.2.0 汇编语言的格式 4.2.1 常量、变量与标号 4.2.2 运算符与表达式,4.2.0 汇编语言的格式,由汇编语言编写的源程序是由许多语句(也可称为汇编指令)组成的。每个语句由14个部分组成,其格式是: 标号 指令助记符 操作数 ;注解 标识符:给指令或某一存储单元地址所起的名字。可由下列字符组成: 字母:A z ; 数字:0 9 ; 特殊字符:?、 、一、$ 。 数字不能作标识符的第一个字符,而圆点仅能用作第一个字符。标识符最长为31个字符。当标识符后跟冒号时,表示是标号。它代表该行指令的起始地址;当标识符后不带冒号时,表示变量;伪指令前的标识符不加冒号。 指令助记符:表示不同操作的指令,可以是8086的指令助记符,也可以是伪指令。 操作数: 指令执行的对象。依指令的要求,可能有一个、两个或者没有。 注解:该项可有可无,是为源程序所加的注解,用于提高程序的可读性。,4.2.1 常量、变量与标号,1. 常量 数值常量:如:010111001,56,94H,0ADH等。 字符串常量 :用单引号括起来的字符串,如 A, abcd等。字符串在计算机中存储的是其ASCLL码。例如:A的值是41H,AB的值是4142H等。 符号常量:常量用符号名来代替就是符号常量。例如: COUNT EQU 3 或COUNT=3,COUNT就是一个符号常量,与数值常量3等价。,4.2.1 常量、变量与标号,2. 变量 变量在数据段、附加数据段或堆栈段中定义,后面不跟冒号。它也可以用LABEL或EQU伪操作来定义。变量经常在操作数字段出现,有三种属性,见下: 段属性:指变量所在段的段首址。 偏移属性:变量的偏移地址,指从段的起始地址到定义变量的位置之间的字节数。 类型属性:变量的类型属性,指该变量定义的字节数。BYTE(1)、WORD(2)、DWORD(4)、FWORD(6)、QWORD(8)、TBYTE(10),4.2.1 常量、变量与标号,在同一个程序中,同样的标号或变量的定义只允许出现一次,否则汇编程序会指示出错。 例 DATA Segment ;数据段 A DB 55 B DW 36H DATA Ends 说明:A 和B是变量。,4.2.1 常量、变量与标号,3. 标号 标号在代码段中定义,后面跟着冒号“:”,它可用LABEL或EQU伪操作来定义;还可以作为过程名定义。标号经常在转移指令或CALL指令的操作数字段出现,用以表示转向地址。标号有3种属性: 段属性:定义标号的段起始地址 偏移属性:标号的偏移地址,是从段起始地址到定义标号的位置之间的字节数。 类型属性:用来指出该标号是在本段内引用还是在其他段中引用的。段内引用的类型属性是Near,段间引用的类型属性是Far。,4.2.2 运算符与表达式,1. 算术运算符 (加)、(减)、*(乘)、/(除)、MOD(取余除) 例如: MOV AL,4*85 ;数值表达式 MOV SI,OFFSET BUF12 ;地址表达式,4.2.2 运算符与表达式,2. 逻辑运算符 AND(与)、OR(或)、XOR(异或)、NOT(非) 说明: 逻辑运算符只能用于数值表达式中,不能用于地址表达式中。 逻辑运算符和逻辑运算指令是有区别的。逻辑运算符的功能在汇编阶段完成,逻辑运算指令的功能在程序执行阶段完成。例如,在汇编阶段, 指令 AND AL,78H AND 0FH 等价于 指令 AND AL,08H,4.2.2 运算符与表达式,3. 关系运算符 EQ(相等) LT(小于) LE(小于等于) GT(大于) GE(大于等于) NE(不等于) 说明: 关系运算符要有两个运算对象。两个运算对象要么都是数值、要么都是同一个段内的地址。运算结果为真时,表示为0FFFFH (-1),运算结果为假时,表示为0000H (0)。 例如: 指令MOV BX,32 EQ 45 等价于 MOV BX,0 指令MOV BX,56 GT 30 等价于 MOV BX,0FFFFH,4.2.2 运算符与表达式,4. 取值运算符 变量和标号具有段属性、偏移属性和类型属性等,要从变量和标号中取出它们的段地址、偏移地址,变量的类型、元素的个数和占用内存的大小等,就要使用取值运算符(又称分析运算符)。这些运算符是: SEG:取段地址 OFFSET:取偏移地址 TYPE :返回变量类型 LENGTH:返回变量所包含的数据个数 SIZE :返回变量的字节数,4.2.2 运算符与表达式,例如:SCORE DW 30 DUP(0) 上述伪指令定义了一个变量SCORE ,取值运算符使用如下: MOV AL, TYPE SCORE MOV AH, LENGTH SCORE MOV BL, SIZE SCORE 则 (AL)=2 ,(AH)=30 ,(BL)=60,4.2.2 运算符与表达式,5. 合成运算符 也称为修改属性运算符,它能修改变量或标号的原有的类型属性并赋予新的类型。这类运算符是PTR和THIS。 PTR的格式: 类型 PTR 表达式 其中类型可以是BYTE、WORD、DWORD、NEAR、FAR,表达式是被修改的变量或标号。 例如: NUM DB 1,3,5,7 则 MOV AX,NUM 非法的!因为NUM是字节定义,而AX是字! 而应改为: MOV AX, WORD PTR NUM,PTR运算符应用例子: 数据段定义: VAR1 DB 10H,18H,25H,34H VAR2 DW 1223H,1200H 代码段定义: MOV AX, WORD PTR VAR1 ;执行后:AX=1810H MOV BL, BYTE PTR VAR2 ;执行后:BL=23H,4.2.2 运算符与表达式, THIS的格式: 新符号名 EQU THIS 类型 原符号名 类型 参数, THIS的功能与PTR相同,只是格式不同。THIS语句中建立一个新的符号名并指定它有THIS后的类型,而新符号名指向下一语句的原符号名的内存地址。 例如用下面的THIS语句代替。 DNUM EQU THIS WORD NUM DB 1,3,5,7 其中DNUM是字型并指向NUM所指的内存单元,DNUM的存取以字为单位,而NUM仍是字节类型。 MOV AX,DNUM ;合法的,4.3 伪指令,1. 符号定义伪指令 等值伪指令EQU 格式:EQU 例如: CONSTANT EQU 256 ;将数256赋以符号名 B EQU BP+8 ;变址引用赋以符号名B AB EQU DATA_ONE +2 ; DATA_ONE必须先定义,否则出错,4.3 伪指令, 等号伪指令 = 例如: EMP=6 或 EMP EQU 6 EQU定义的表达式名不允许重复使用。而伪指令则允许重复使用。,4.3 伪指令, 定义符号名伪指令LABEL LABEL伪指令可以定义变量或标号. 格式: LABEL LABEL只指出所定义的变量或标号的类型,可以是BYTE、WORD、DWORD、NEAR、FAR。具体的变量或标号的段属性和偏移属性则由下一条可分配内存的变量或标号的属性决定。例如: DATW LABEL WORD DATB DB 20H DUP(0) FLPT LABEL FAR NLPT: MOV AX,BX,4.3 伪指令, 解除定义伪指令PURGE:解除指定符号的定义。 格式:PURGE 解除符号定义后,可用EQU重新定义。 例如: Y1 EQU 7 ;定义Y1的值为7 PURGE Y1 ;解除Y1的定义 Y1 EQU 36 ;重新定义Y1的值为36,4.3 伪指令,(5)DUP按照给定的次数来复制某个(或某些)操作数,可以避免多次重复输入同一个数据。 例1: Data1 DB 0FFH,0FFH,0FFH,0FFH,0FFH,0FFH Data2 DB 6 DUP(0FFH) 例2:操作数?可以保留存储空间,但不存入数据。 Array1 DB 2 DUP(0,1,2,?) Array3 DB 100 DUP(?),4.3 伪指令,2. 数据定义伪指令 格式: 变量 助记符 操作数,操作数;注释 该类伪指令用来定义存贮空间及其所存数据的长度。 DB:定义字节,即每个数据是1个字节。 DW:定义字,即每个数据占1个字(2个字节)。 DD:定义双字,即每个数据占2个字。低字部分在低地址,高字部分在高地址。 DQ:定义4字长,即每个数据占4个字。 DT:定义10个字节长,用于压缩式十进制数据。 例如:DATA1 DB 10H,6,78H,100 表示从DATA1单元开始连续存放10H,6,78H,100,共占4个字节地址。,4.3 伪指令,定义数据伪指令 DATA1 DB 20H DATA2 DW 0240H,1000H DATA3 DB (-1*3),(15/3) DATA4 DD 12345H DATA5 DB 3210 DATA6 DW AB,C,D DATA7 DB ? DATA8 DD ? DATA9 DB 5DUP(00) DATA10 DW 3DUP(?),4.3 伪指令,课后练习 例1:请图示下面伪指令定义的数据在内存中的存放形式。 (1)BUF1 DB 12,12,12H,2*6,-1 (2)BUF2 DW 12,12H,1234H (3)BUF3 DB 2 DUP(5,4,3DUP(8),4.3 伪指令,例2:下面是一个定义数据的程序段,设DATA值为1200H,请图示各数据在内存的存放形式。 Data segment org 100H Buf1 DB 10H,20H,30H Buf2 DW Buf1 Buf3 DD Buf2 Count EQU Buf2-Buf1 Buf4 DW Buf2-Buf1 Data ends,4.3 伪指令,3. 段定义伪指令 SEGMENT和ENDS 段定义伪指令 该指令能对程序分段,其格式为: 段名 SEGMENT 定位类型组合类型类别 段名 ENDS,4.3 伪指令,DATA1 SEGMENT DATA1 ENDS STACK1 SEGMENT STACK STACK1 ENDS CODE1 SEGMENT ASSUME CS:CODE1,DS:DATA1,SS:STACK1 MOV AX,DATA MOV DS,AX MOV AX,STACK MOV SS,AX CODE1 ENDS,4.3 伪指令, ASSUME 段寄存器指派伪指令 该伪指令用来通知汇编程序哪一个段寄存器是该段的段寄存器 格式: ASSUME 段寄存器:段名,段寄存器:段名 注意:由于ASSUME伪指令只指明某一个段地址应存于哪一个段寄存器中,并没有包含将段地址送入该寄存器的操作。因此除CS外,DS、ES 和SS中的段地址要在程序中通过MOV指令装入。,4.3 伪指令,例子: DATA1 SEGMENT DATA1 ENDS STACK1 SEGMENT STACK STACK1 ENDS CODE1 SEGMENT ASSUME CS:CODE1,DS:DATA1,SS:STACK1 MOV AX,DATA MOV DS,AX MOV AX,STACK MOV SS,AX CODE1 ENDS,装入DS数据段寄存器,装入SS堆栈段寄存器,4.3 伪指令, ORG 移动地址指针的伪指令 格式为: ORG 常量表达式 该指令指定地址指针相对于当前指针的偏移位置,常用表达式给出偏移量。当指定新的地址指针以后,其后的程序和数据就从此指针指示的起始地址开始存放。例如 ORG 100H 地址计数器用来保存当前正在汇编的指令的地址,这个地址指针用$表示。如ORG $+5 ,则表示地址指针从当前地址跳过5个字节。,4.3 伪指令,4. 过程定义伪指令PROC和ENDP 在程序设计中,可将具有一定功能的程序段看成为一个过程(相当于一个子程序),它可以被别的程序调用。一个过程由伪指令PROC和ENDP来定义。 过程名 PROC 类型 过程体 RET 过程名 ENDP 其中过程名是为过程所起的名称,不能省略,过程的类型由FAR(远过程,为段间调用)和NEAR(近过程,在本段内调用)来确定,如果缺省类型,则该过程就默认为近过程。ENDP表示过程结束。过程体内至少应有一条RET指令,以便返回被调用处。过程可以嵌套,也可以递归使用。,4.3 伪指令,4. 过程定义伪指令PROC和ENDP DELAY PROC MOV BL,10 DELY:MOV CX,2801 WAIT:LOOP WAIT DEC BL JNZ DELY RET DELAY ENDP,4.3 伪指令,5. 程序标题伪指令TITLE Title伪指令指定一个标题,以便在列表文件每一页的第一行打印出这个标题。一般放置在程序的第一行开始处。 格式:TITLE 文本 其中,文本是用户给出的字符串,要求长度不超过6个字符。,4.3 伪指令,6、EVEN 伪指令 使下一个变量或指令开始于偶数字节地址。,4.3 伪指令,7. 基数控制伪指令 二进制数 由一串0和1组成其后跟以字母B,如00101100B 十进制数 由09的数字组成的数。一般情况下,后面不必加上标记,在指定其它基数的情况下,后面可跟字母D,例如178D。 十六进制数 由09及AF组成的数,后面跟字母H。这个数的第一个字符必须是09,所以如果第一个字符是AF时,应在其前面加上数字0,如0FFFFH。,4.3 伪指令, 八进制数 由数字07组成的数,后面可跟字母O或Q,如1777O。 .RADIX RADIX伪指令可以把默认的基数改变为216范围内的任何基数。格式如下: .RADIX EXPRESSION 字符串 字符串可以看成串常量,可以用单引号或双引号把字符串放在其中,得到的是字符串的ASCII码值,例如,ABCD。,4.4 宏指令,宏汇编是一种与子程序类似而又独具特色的简化程序设计的工具。宏汇编给用户提供了自行设计指令并使用的手段,也就是用一条自定义的指令来代替一段完成某种功能的程序段,这种自定义的指令称为宏指令。 宏汇编主要包括3个步骤:宏定义,宏调用和宏展开。,P128,4.4 宏指令,1.宏指令定义 将一段代码定义成宏指令,相当于用户自定义了一条指令。格式如下: 宏指令名 MACRO 形式参数1,形式参数2, 形式参数N ;宏指令体(宏体) ENDM 例4.1 定义一条从键盘输入一个字符的宏指令INPUT input macro mov ah 1 int 21h endm,例4.2 定义一条换行宏指令LF LF MACRO MOV DL,10 10 是换行符的ASCII码 MOV AH,2 INT 21H ENDM 例4.3 定义一条回车宏指令CR CR MACRO MOV DL,13 13 是回车符的ASCII码 MOV AH,2 INT 21H ENDM,4.4 宏指令,2. 宏调用 在程序需要的地方插入宏指令,其语法与其他汇编语言指令相同。 宏指令名 实际参数1,实际参数2, 实际参数N 见例4.4 定义一条INOUT宏指令,既可以引用它输入一串字符,也可以引用它来显示一串提示字符。exmacro.asm,; 定义一条InOut指令,既可以引用它输入一串字符,也可引用它显示一串提示字符 inout macro x, y mov ah,x lea dx,y int 21h endm data segment input db Please input any characters:,$ keybuff db 10,11 dup(?),13,10,$ data ends code segment assume cs:code ,ds:data start: mov ax,data mov ds,ax inout 9,input ;显示一串提示符的宏指令调用 lf cr inout 10,keybuff ;输入一串字符串的宏指令调用 inout 9,Keybuff+2 ;显示输入的一串字符串的宏调用 mov ah,4ch int 21h code ends end start,4.4 宏指令,3. 宏展开 汇编时,汇编程序并不对宏定义指令进行汇编,只有在宏调用时才对宏指令体进行语法检查和代码块的插入。这个过程称为宏展开(即在汇编源程序是,在宏调用的位置用宏定义的程序代码代替宏指令)。 在masm汇编生成的列表文件(.lst)中,可以看到宏展开。用记事本打开可以看到宏展开的地方有1作标志。 见EXMACRO.LST,4.5 系统功能调用,4.5.1 DOS软中断指令 8086系统规定对这些功能的调用,统一使用软中断INT指令,格式如下: INT n 其中,n是中断类型码。,4.5 系统功能调用,4.5.2 DOS系统功能调用(INT 21H) 带显示的单字符键盘输入(1号功能) 格式: MOV AH,1 INT 21H 输出单字符(2号调用) 格式: MOV DL,A;A字符的ASCII码置入DL中 MOV AH,2 INT 21H,4.5 系统功能调用, 不带显示的单字符键盘输入(7号、8号调用) 字符串输出(9号调用) 字符串输入(0AH号调用) 返回操作系统(4CH号调用) 格式: MOV AH,4CH INT 21H,4.6 汇编语言程序设计举例,用这三种基本结构作为表示一个良好算法的基本单元。 顺序结构 选择结构 循环结构:它又称重复结构,即反复执行某一部分的操作。有两类循环结构:当型(WHILE型)循环结构和直到型(UNTIL型)循环结构。,图4.3 顺序结构图,箭头:程序执行的方向 方框:语句 棱形框:条件判断 学会画程序结构流程图,4.6.1 顺序程序结构,例4.5 编程序计算:SUM=3*(X+Y)+(Y+Z)/(Y-Z),其中X、Y、Z都是16无符号数。假设运算过程中间结果都不超出16位二进制数的范围,要求结果存入SUM单元。程序片段如下:,MOV AX,X ;取X ADD AX,Y ;AXX+Y MOV CX,3 MUL CX ;DX:AX3*X+Y MOV CX,AX ;CX3*X+Y保存 MOV AX,Y ;取Y ADD AX,Z ;AXY+Z XOR DX,DX ;DX0 MOV BX,Y ;取Y SUB BX,Z ;BXY-Z DIV BX ;AXY+Z/Y-Z的商 ADD AX,CX ;AX3*X+Y+Y+Z/Y-Z MOV SUM,AX ;存结果,4.6.1 顺序程序结构,开始,结束,从存储单元取得两个数,并相加,将高4位转化为ASCII字符码输出,将低4位转化为ASCII字符码输出,例4.6程序流程结构图,4.6.1 顺序程序结构,例4.6 将两个字节数据相加,并存放到一个结果单元中。,DATA SEGMENT AD1 DB 4CH ;定义第1个加数 AD2 DB 25H ;定义第2个加数 SUM DB ? ;定义结果单元 DATA ENDS CODE SEGMENT ASSUME CS:CODE,DS:DATA START:MOV AX,DATA MOV DS,AX MOV AL,AD1 ;取出第1个加数 ADD AL,AD2 ;和第2个加数相加 MOV SUM,AL ;存放结果 MOV BL,AL ;显示16进制结果 MOV CL,4,4.6.1 顺序程序结构,4.6.1 顺序程序结构,SHR AL,CL ; 右移4位 AND AL,0FH ;高4位清0 ADD AL,30H ;加30H,变成ASCII码。 MOV DL,AL ;显示高4位 MOV AH,2 INT 21H MOV AL,BL AND AL,0FH ADD AL,30H MOV DL,AL ;显示低4位 MOV AH,2 INT 21H MOV AH,4CH ;返回DOS INT 21H CODE ENDS END START,4.6.1 顺序程序结构,数据处理并显示过程,ASCII码,二进制数,Ascii码(串),计算机直接按二进制数的运算规则来进行算术运算,4.6.2 分支程序设计,分支程序结构可以有两种形式,如下图所示。它们分别相当于高级语言中的IF_THEN_ELSE语句和CASE语句,适用于要求根据不同条件作不同处理的情况。IF_THEN_ELSE语句可以引出两个分支。CASE语句则可以引出多个分支。不论哪一种形式,它们的共同特点是:运行方向是向前的,在某一种特定条件下,只能执行多个分支中的一个分支。,4.6.2 分支程序设计,例4.7 编制程序实现符号函数。 1 X0 Y= 0 X=0 (-128X+127) -1 X0 程序部分如下:,图4.6 例4.7程序流程图,CMP X,0 JL PNUM ;X0转移到PNUM JZ ZERO ;X=0转移到ZERO MOV Y,1 JMP EXIT ;X0 PNUM: MOV Y,-1 JMP EXIT ;X0 ZERO: MOV Y,0 ;X=0 EXIT: ,4.6.2 分支程序设计,3.利用地址跳转表实现分支 利用地址跳转表的方法主要用于三路分支(或以上)的情况,类似CASE结构。 例4.8 在调用DOS文件管理功能时,如出现了错误(如使用了非法功能号),DOS则根据AX中的错误码,将相应的错误信息显示出来.(AX)=15各表示一种错误,其错误信息分别为ER1ER5.AX除15之外的数码是无效(代码见 ch4_8table.doc,本题关键是找到AX与地址跳跃表的字符串地址ER1ER5的对应关系)。,4.6.2 分支程序设计,title ch4_8.asm data segment outrang db Error code is not in valid range(15),0dh,0ah,$ er1 db Invalid function number,0dh,0ah,$ er2 db File not found,0dh,0ah,$ er3 db Path not found,0dh,0ah,$ er4 db Too many open file,0dh,0ah,$ er5 db Acess violation,0dh,0ah,$ even ertab dw er1,er2,er3,er4,er5 data ends,code segment assume cs:code,ds:data show_err proc far start: mov si,data mov ds,si push ax ;保存正在工作的寄存器 push bx push dx mov ax,2 ;假设AX=2 cmp ax,5 ;跟5比较 jg outr ;大于5则超出范围 cmp ax,1 ;小于5,则看是否大于1 jge tab_addr ;若大于1则查找错误信息表地址 outr: lea dx,outrang ;超出范围时的错误信息 jmp short disp_msg ;跳转至输出信息,4.6.2 分支程序设计,4.6.2 分支程序设计,tab_addr: mov bx,ax ;(AX)-1)*2=bx dec bx shl bx,1 mov dx,ertabbx ;将错误信息首地址送给dx,以便输出 disp_msg: mov ah,09 ;输出错误信息字符串 int 21h pop dx ;弹出工作寄存器 pop bx pop ax,4.6.2 分支程序设计,mov ax,4c00h int 21h show_err endp code ends end start,作业,习题4 第1,2,3题 第5题,编程并画出程序流程图,4.6.3 循环程序设计,1. 循环程序结构 DO_WHILE结构 :DO_WHILE结构把对循环控制条件的判断放在循环的入口,先判断条件,满足条件就执行循环体,否则就退出循环。 DO_UNTIL结构:DO_UNTIL结构则先执行循环体,然后再判断控制条件,不满足条件则继续执行循环操作,一旦满足条件则退出循环。,(a) DO WHILE结构,(b) DO UNTIL结构,4.6.3 循环程序设计,循环程序都可由如下三部分组成: 设置循环的初始状态: 如设置循环次数的计数值,以及为循环体正常工作而建立的初始状态等。 循环体:循环工作的主体,它由循环的工作部分及修改部分组成。 循环控制部分,与循环有关的指令,LOOP 标号 ;基本循环指令 LOOPZ/LOOPE 标号 ;为零/相等时循环 LOOPNZ/LOOPNE 标号;不为零/不等时循环 说明 条件循环指令除测试CX外还测试ZF,因此要注意将条件循环指令紧接在形成ZF的指令之后 在多重循环的程序结构中,注意对循环计数器的保存与恢复。循环指令不影响条件码。,4.6.3 循环程序设计,2. 循环控制方法 循环的结束判断是循环程序的一个重要部分,控制循环的执行并判断是否结束循环的方法主要有三种:计数控制、条件控制、逻辑尺控制。下边分别进行讨论。 计数控制 这是一种最常用的循环控制方法,适用于事先已知循环次数的情况。可用循环指令LOOP实现,也可用条件转移指令实现。,4.6.3 循环程序设计,例4.9: 在首地址为BUFF的内存缓冲区中,存放着20H个带符号字数据。编制程序找出其中的最小值,并将最小值存入MIN单元。程序片段如下:,LEA SI,BUFF ;设地址指针 MOV CX,20H ;CX循环次数 MOV AX,SI ;AX第一个数据 INC SI INC SI ;SI指向第二个数 DEC CX AGAIN:CMP AX,SI JLE NEXT ;小于或等于时转移 MOV AX,SI NEXT: INC SI INC SI ;修改地址指针指向下一个数 LOOP AGAIN MOV MIN,AX,完整程序见ch4-9.asm,4.6.3 循环程序设计, 条件控制 适用于事先不知道循环次数的场合,但可以用给定的某种条件来判断是否结束循环。 例4.10 编程统计AX寄存器中1的个数,并将结果存入SUM单元,4.6.3 循环程序设计,程序片段如下: MOV BL,0 ;计数单元BL清0 AGAIN:OR AX,AX ;测试AX=0? JZ EXIT ;若 AX=0,则转移到结束点。 SHL AX,1 ;将AX最高位移至CF JNC NEXT ;CF=0,转去AGAIN继续 INC BL ;CF0,BL加1 NEXT:JMP AGAIN EXIT:MOV SUM,BL,4.6.3 循环程序设计,3.逻辑尺控制 适用于没有规律但必须连续执行的情况。 例4.11 编写一个显示程序,要求显示A和B14次,显示次序为A显示3次,B显示1次,B显示1次,A显示4次,B显示3次。分析: 设逻辑尺:0001101000011100 0表示显示A 1表示显示B 逐位测试逻辑尺,是0则执行显示A的分支,是1则执行显示B的分支代码见ch4_11logicrule.doc,Title逻辑尺 Data segment A db * B db Logic_rule dw 1A1CH Data ends Code segment assume cs:code,ds:data Start: mov ax,data Mov ds,ax Mov cx,14 Mov bx,logic_rule Next : Shl bx,1 Jc showB,Mov dl,A Jmp Display showB: Mov dl,B Display: Mov ah,02h Int 21h Loop next Mov ax,4c00h Int 21h Code ends end start,4.6.3 循环程序设计,4.6.3 循环程序设计,3. 双重循环程序设计 例4.12编制程序实现延时1ms。延时程序就是让计算机执行一些空操作或无用操作,来占用CPU的时间,从而达到延时的目的。通常用循环程序实现。程序片段如下: MOV CX,374 DELAY1:PUSHF ;10T POPF ;8T LOOP DELAY1 ;3.4T,4.6.3 循环程序设计,上边程序段的循环体和循环控制部分是由指令PUSHF、POPF和LOOP构成。这三条指令执行所花费的时钟周期个数和为10+8+3.4=21.4。若CPU的主频为8MHz,那么它的时钟周期为0.125S。如果要实现延时1ms,则该循环体重复连续执行的次数为: 循环次数=1ms/(0.125S21.4)374,4.6.3 循环程序设计,如果要延时100 ms,那么只需将这个程序再执行100次,从而构成一个双重循环。其程序片段如下: MOV BL,100 ;4T1 DELAY2:MOV CX,374 ;4T2 DELAY1:PUSHF ;10T POPF ;8T LOOP DELAY1 ;3.4T DEC BL ;2T JNZ DELAY2 ;8T 显然,该程序的准确延时时间为:T=4T+100(4T+21.4T374+2T+8T)=100.22ms,4.6.3 循环程序设计,延时程序: Mov di,30000 Delay: Mov si,30000 Delay1: dec si Jnz Delay1 dec di jnz Delay,4.6.4 子程序设计,1. 子程序的调用和返回 过程具有特定功能的代码块 过程名 proc attribute 过程名 endp 其中,过程名为标识符,又是子程序入口的符号地址,attribute是类型属性,可以是Near或Far 调用程序和过程在同一个代码段中则使用Near属性 调用程序和过程不在同一个代码段中则使用Far属性 子程序用CALL指令调用,返回用ret指令。,调用子程序的过程:,CALL ProcA,主程序,RET,子程序,下一条指令,ProcA:,断点(CS:IP) 放入堆栈区,4.6.4 子程序设计,例4.24 子程序的定义、调用和返回示意 CODE1 SEGMENT CALL PROC1 AAA: PROC1 PROC RET PROC1 ENDP PROC2 PROC FAR RET PROC2 ENDP CODE1 ENDS CODE2 SEGMENT CALL PROC2 BBB: CODE2 ENDS,例4.24中,CALL PROC1汇编后形成段内调用,CALL PROC2形成段间调用。AAA和BBB是两个返回地址。,4.6.4 子程序设计,子程序最后一条执行的指令一定是返回指令RET,RET指令能按照CALL指令的不同格式,由汇编程序汇编形成段内返回(过程PROC1中的RET指令)和段间返回(PROC2中的RET指令),并将控制返回到主程序断点。如在例4.24中,子程序PROC1返回后,从AAA处开始执行,子程序PROC2返回后,从BBB处开始执行。,4.6.4 子程序设计,2.编制子程序时的注意事项 子程序设计要求:通用性强,独立性好,程序目标代码短,占用内存少,执行速度快,结构清晰,有详细的功能、参数说明。 需要注意如下三点: 参数传递 主程序每次调用子程序时,必须给它赋予处理的数据到约定的地址单元中,这些数据被称为参数。 主程序和子程序间的数据传递称为参数传递。 主程序传递给子程序的参数称为子程序的入口参数, 子程序返回给主程序的参数称为出口参数。,4.6.4 子程序设计, 信息保护 保护现场:将子程序用到的寄存器压入堆栈保护的过程称为保护现场。 恢复现场:将寄存器从堆栈中弹出恢复的过程。 保护和恢复现场的工作可以在调用程序中进行,也可以在子程序中进行。 子程序的说明 子程序名、功能、技术指标 子程序入口、出口参数 子程序使用到的寄存器和存储单元 是否又调用其他子程序,4.6.4 子程序设计,3.主程序与子程序之间的参数传递 (1) 利用寄存器和存储区传送参数 寄存器传递参数:这种方式方便,快速,但只适合参数较少的情况. 存储区传递参数:主程序和子程序之间可以利用指定的存储变量进行参数传递,这种方式适合参数较多的情况。见CH414_1.doc (2) 利用地址表传送参数 转子程序前,将参数地址放入一个表中,将表的首地址作为入口参数传递给子程序,由子程序根据参数表中的地址取出对应参数。见ch414_2.doc,4.6.4 子程序设计,(3)用堆栈传递参数 堆栈适合传送参数多,并且子程序有嵌套、递归调用的情况,转子程序前,将子程序用到的参数压入堆栈; 进入子程序后,由子程序从堆栈中取出所用参数; 对于这种参数传递方法,在子程序中经常采用使用带位移量的返回指令RET n,它可以在恢复断点后,将堆栈指针SP加n,从而跳过参数区,使SP指向参数压入堆栈前的那个单元。 见ch414_3.doc,略,4.6.5实用程序举例排序,一. 排序 例4.17 设有一个首地址为ARRAY的N字节数组,编程序将它们按从大到小的顺序排列 算法设计:采用冒泡法排序(从大到小) 。,8 16 15 85 32,原始数据,第1趟,第2趟,第3趟,第4趟,16 15 85 32 8,16 85 32 15 8,85 32 16 158,85 3216158,图4.13 冒泡排序法程序流程 从大到小排序 有N个数,则排序N-1次 每一次排序过程,两两比较,若前一个小于后一个则交换(即小的交换到后面),否则继续。 双重循环实现,外循环控制比较次数,内循环控制相邻元素的比较,第i轮比较的内循环次数是N-i次。 标志位的设立是提高程序效率。,课后思考:若要求从小到大排序,如何实现?,8 16 15 85 32,原始数据,8 15 16 32 85,第1趟,第2趟,8 15 16 32 85,第3趟,8 15 16 32 85,4.6.5实用程序举例代码转换,二. 代码转换 数据输入输出过程,ASCII码,键盘输入,内部存储,二进制数,显示,Ascii码(串),计算机直接按二进制数的运算规则来进行算术运算,字符码与二进制数的转换,二进制十六进制,BCD码十进制数,二进制十进制数,4.6.5实用程序举例代码转换,(1) ASCII字符码转换为二进制数 从键盘上获得的是ASCII码,需转换成二进制数才能参数算术逻辑运算。以输入数字78(ASCII码为3738H)为例,转换的过程如

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论