资源描述
单击此处编辑母版标题样式,单击此处编辑母版文本样式,第二级,第三级,第四级,第五级,*,单击此处编辑母版标题样式,单击此处编辑母版文本样式,第二级,第三级,第四级,第五级,*,第4章 汇编语言程序设计,本掌重点:,汇编语言的基本语法规则及其使用方法,伪指令语句的格式、类别及功能,简化段定义结枸中常用的伪指令,汇编语言程序结构,8086/8088汇编语言程序设计,本掌难点:,汇编语言语句中使用的各种操作数、表达式、运算符、操作符,汇编语言伪指令,汇编语言程序设计,4.1 汇编语言源程序和汇编程序,4.1.1 机器语言、汇编语言和高级语言,1.机器语言用“0”、“1”代码书写的一组二进制数,计算机能够直接识别并直接运行的一种语言。,2.汇编语言是机器语言的简便形式,其特点之一是用英文缩写词(助记符)表示指令,另一特点就是操作数(数据或地址)用符号表示。,3.面向对象语言采用高级语言和汇编语言混合编程,并可彼此互相调用,共享数据结构及数据信息,这样充分发挥各种语言的优势。,4.1.2 汇编语言源程序和机器语言目标程序,图4-1 源程序的汇编过程,4.1.3 汇编和汇编程序,1.汇编:汇编语言(源)程序不能被计算机识别和执行必须经过翻译。把源程序翻译成机器语言目标程序的过程,叫做汇编。,2.汇编程序(ASM):完成汇编任务的程序叫做汇编程序。它是一种通用系统软件,能把汇编语言翻译成计算机能够识别和执行的目标程序。,3.宏汇编程序(MASM):宏汇编则在基本汇编基础上进一部扩展了功能。能够把源程序中一组汇编语言语句序列定义为一条宏指令的汇编程序,叫做宏汇编程序。,4.汇编时一般采用MASM汇编程序。,4.2 MASM宏汇编语言程序的语句类型和格式,1.定义:在汇编后可产生相应的(目标)代码、对应着机器的某种操作的语句称为指令语句。,2.指令语句格式:一个语句行是由4个部分组成,指令语句格式,:,NEXT,:,ADD AX,,,BX,;,1.定义:伪指令语句即不是真正的指令语句,它是CPU不执行的语句。在汇编后它本身不产生目标代码,只为汇编程序提供汇编时所需要的控制信息。,2.语句格式:,伪指令语句格式,3.例句:,VAR DB20H,30H;,DB 20,30,4.2.3宏指令语句:,1.定义:在程序开头,把经常要使用的一个汇编语句序列用一条指令代替(即定义成一个宏符号),这种指令就称宏指令。,2.语句格式:,宏指令名MACRO形式参数1,形式参数2,(宏定义伪指令语句序列),ENDM,例:试定义从键盘输入字符串的宏指令.,KBIN MACRO A ;KBIN为宏指令名,A为输入参数,MOV AH,0AH ;10号功能调用,键入字符串,MOV DX,OFFSET A;缓冲区A首地址偏移量送DX,INT 21H ;,ENDM ;宏定义结束,4.3 8086/8088汇编语言中的标识符、运算符及操作符,4.3.1 常量和数值表达式,1.常量:是指那些在汇编时已经有确定数值的量,常量又分:,(1)数值常量以数值形式出现在指令语句中,这种常量称为数值常量。,(2)符号常量将那些经常使用的数值预先给它定义一个名字,然后用该名字来表示该常量,这种常量称为符号常量。,2.数值表达式:,所谓表达式是由各种操作数、运算符和操作符(+、-、*、/等)连接起来的式子。,4.3.2 变量和地址表达式,1、变量:通常是指存放在存储单元中的值。在程序中作为存储器操作数被引用。变量定义一般在数据段中,故一个变量被定义后就有了三种属性:段属性、偏移属性和类型属性。,2、地址表达式:由常量、变量、标号、寄存器(如:BX、BP、SI、DI)的内容(用寄存器名加方括号表示)以及一些运算符组成的式子称为地址表达式。地址表达式主要用来表示指令语句中的操作数。因此,也具有三属性。,3、变量的三属性,(1)段属性(SEEMENT)段基址,即标号或者变量所在段的段地址。,(2)偏移属性(OFFSET)段内偏移地址,即标号或变量所在单元的地址与所在段的段起始地址之差。,(3)类型属性(TYPE)变量的类型是指存取该变量中的数据所需要的字节数,类型有BYTE(字节)、WORD(字)、DWORD(双字)、DQ(四字)、DT(十字节)5种。,4.3.3 运算符,1、算术运算符:有(加)、(减)、*(乘)、/(除)、MOD(取余)、SHL(左移)、SHR(右移)共7种。,例:已知源程序指令格式如下:,DA EQU 300,MOV AX,,,D-80,MOV BX,,,DA MOD 100,MOV CX,,,DA/100,MOV DH,,,01100100B SHR 2,汇编后,计算表达式形成指令如下:,DA EQU 300,MOV AX,220,MOV BX,0,MOV CX,3,MOV DH,,,19H,2,、逻辑运算符:是按位操作的,AND,(与)、,OR,(或)、,XOR,(异或)、,NOT,(非),只适用于数值表达式。,例:IN AL,PORT,AND DX,PORT AND 0FEH,OUT DX,AX,解:后面一个AND为运算符,汇编时,计算表达式得到一个端口号。,设原输入端口号PORT为80H,则,1000 0000,表达式PORT AND 0FEH的值为80H,1111 1110,1000 0000,设原输入端口号PORT为81H,则,1000 0001,计算表达式仍得到80H,1111 1110,1000 0000,前面一个AND(指令助记符)在运行程序时,将(DX)与计算出的表达式相“与”。结果送DX中,DX为输出端口号。,IN AL,PORT;AL=(80H),AND DX,80H;,OUT DX,AX,3、关系运算符:这类运算符有EQ、NE、LT、GT、LE和GE。关系运算符的两个操作数必须同是数值或同是一个段内的两个存储器地址。比较时,若关系成立(为真),则结果为全“1”,若关系不成立(为假),则结果为全“0”。其结果值在汇编时获得。,例:MOV AX,10H GT 16,ADD BL 6 EQ 0110B,MOV CX,(PORT LT 5)AND 100)OR (PORT GE 5)AND 200),解:汇编时,形成指令,MOV AX,0,ADD BL,0FFH;若满足PORT5,则PORT LT 5 逻辑取值为真,,即,(111 AND 100)OR (000 AND 200),100 OR 000,MOV CX,100 ;当端口地址PORT,0,已知SGN(X)0,X=0,-1,X,0,INT 21H,RET ;,解:据题意设总共温度补偿须循环16次。,MOV BX,DX ;,1 汇编语言源程序基本结构特点:,格式:END 表达式 ;,END START,利用DOS功能调用的4CH号功能,返回DOS,MOV DL,BX,(111 AND 100)OR (000 AND 200),4、利用跳转表实现分支,(宏定义伪指令语句序列),画程序流程图,目的是:,解:,这是一个三分支的程序,使用两条条件转移指令来实现。分支的条件是将给定的X与0进行比较。,源程序如下:,利用比较/转移指令实现,DATA SEGMENT,X DB XXH,SGNX DB?,DATA ENDS,STACK SEGMENT PARA STACK STACK,DB 20H DUP(0),STACK ENDS,CODE SEGMENT,ASSUME CS:CODE DS:DATA,MAIN PROC FAR,START:PUSH DS,XOR AX,AX,PUSH AX,MOV AX,DATA,MOV DS,AX,MOV AL,X,CMP AL,0 ;X0,JGE BIG ;若X0转BIG,否则,MOV SGNX,-1;X0,1送SGNX单元,JMP NEXT,EQUL:MOV SGNX,0 ;X=0,0送SGNX单元,NEXT:RET,MAIN ENDP,CODE ENDS,END START,3、利用比较/转移指令实现三个分支结构(分支结构1+分支结构2+分支结构3),例:编写一个程序把三个无符号单字节数从大到小进行排列。,解:排序算法中有三个分支结构,其排序程序流程图,源程序如下:,STACK1 SEGMENT STACKSTACK,DW 64H DUP(?),STACK1 ENDS,DATA SEGMENT,BUF DB 84H,32H,56H;待排序数据,DATA ENDS,CODE SEGMENT,ASSUME CS:CODE,DS:DATA,SS:STACK1,START:MOV AX,DATA,MOV DS,AX ;初始化DS,MOV SI,OFFSET BUF;设置地址指针,MOV AL,SI ;将数据由内存读入寄存器,MOV BL,SI+1CMP AL,BL,JAE NEXT1,MOV CL,SI+2,;比较AL与BL,;第1个分支结构,CMP AL,BL,JAE NEXT1,XCHG AL,BL ;(AL)大CMP AL,BL,NEXT1:;比较AL与CL,;第2个分支结构,XCHG AL,CLCMP AL,BL,JAE NEXT3,NEXT2:;比较BL与CL,;第3个分支结构,XCHG BL,CL,NEXT3:MOV SI,AL ;存结果到内存,MOV SI1,BL;,MOV SI+2,CL;,MOV AH,4CH,INT 21H,CODE ENDS,END START,CMP AL,BL,JAE NEXT2,CMP AL,BL,JAE NEXT3,4、利用跳转表实现分支,例:设有8个子程序,已知其入口地址分别为SUB0,SUB1,SUB7(同在一个段内)依次放在ADRTAB开始的地址表中每个地址占两个字节。低字节在低地址,高字节在高地址。当键盘输入07中任一数字i时,便可分支到相应的例行子程序中执行,实现多路分支。,解:,(1)首先建立一个跳转表,表中存放每个子程序的入口地址。利用此表可找到存放子程序入口地址的位置(叫做查表地址)设地址表基地址为ADRTAB.,(2)根据键入的数字i计算查表地址:,查表地址跳转表首地址偏移地址ADRTAB2*i (i=07中任一值),源程序如下:,DATA SEGMENT,ADRTAB DW SUB1,SUB2,SUB8 ;定义入口地址表,KEYIN DB?,DATA ENDS,STACK ENDS,CODE SEGMENT PARA STACKSTACK,DW 40 DUP(?),STACK ENDS,CODE SEGMENT,ASSUME CS:CODE,DS:DATA,SS:STACK,START PROC FAR,PUSH DS,MOV AX,0,PUSH AX,MOV AX,DATA,MOV DS,AX,MOV AH,01 ;从键盘输入07中的一个数,INT 21H ;键盘输入的ASC码在AL中,COMPUT:MOV AH,0 ;2*i,AND AL,0FH,ADD AL,AL,MOV BX,OFFSET ADRTAB,ADD BX,AX ;求查表地址,JMP WORD PTRBX ;转入相应入口地址,SUB0:;8个例行子程序,SUB1:,SUB7:,RET,START ENDP,CODE ENDS,END START,1.循环程序的基本结构形式:,(1)“先执行后判断”结构:,这种结构至少执行一次循环体,即进入循环后先执行一次循环体,然后再判断循环是否结束。如图4-(a)所示。常用于循环次数已知的场合。,(2)“先判断后执行”结构:,这种结构的特点是进入循环后,首先判断循环结束的条件,再由判断结果决定是否执行循环体的程序。也可能一次皆不执行循环体如图(b)所示。用于循环次数未知,需要找出控制循环结束条件时常用。,循环程序程序两种基本结构,参数初始化,工作部分,修改参数,控制部分循环结束?,N,Y,(,a)先执行后判断,参数初始化,控制部分循环结束?,工作部分,修改参数,N,Y,(b)先判断后执行,2.循环控制方法:,每个循环程序必须选择一个循环控制条件来控制循环的运行和,结束,所以循环控制部分是设计循环程序的关键。循环控制方法通常主要有3种。,(1)计数控制:循环次数已知,每执行循环体一次,加上或者减1。,(2)条件控制:循环次数未知,根据循环条件是否满足控制循环,(3)逻辑尺控制:在多次循环过程中,需分别进行不同的操作时,可通过建立位串(0或1)信息(此称逻辑尺)控制循环。,例:统计“1”的个数。在内存的ONE单元中有一个16位二进制数。要求统计出该X单元中含1的个数,并存入RES单元。试编写此程序。,解:该程序采用“先判断,后执行”结构。若ONE单元中的数全零,则不需进行统计,立即结束循环。用CX寄存器作为计1计数器,统计1的个数采用移位方法,16次移位后AX=0,,源程序如下:,DATA SEGMENT,X DW 6543H,RES DW?,DATA ENDS,CODE SEGMENT,ASSUME CS:CODE,DS:DATA,START:MOV AX,DATA,MOV DS,AX ;初始化DS,MOV CX,0 ;记1计数器清零,MOV AX,X ;取ONE内容到AX,L1:AND AX,AX ;控制器循环,JZ EXIT,SAL AX,1 ;循环体,JNC L2,INC CX,L2:JMP L1,EXIT:MOV RES,CX ;存结果,MOV AX,4C00H,INT 21H,CODE ENDS,END START,解:据题意设总共温度补偿须循环16次。,其中第0,1,4,5,6,10,11,15次要求执行COMP0(+1)计算,,其余第2,3,7,8,9,12,13,14次要求执行COMP1(-1)计算。,(1)设指针,(2)逻辑尺长度计数初值,(3)i=0RES结果修改指针计数1结束i=i+1读逻辑尺BXi=?=1=0计数器=0?NY,源程序如下:,DATA SEGMENT,BUF DB T0,T1,T1,T0,RES DB 16 DUP(?),LOGIR DW 738CH,DATA ENDS,CODE SEGMENT,SSUME CS:CODE,DS:DATA,START:MOV AX,DATA,MOV DS,AX,LEA SI,BUF,LEA DI,RES,MOV BX,LOGIR,MOV CX,16,AGA:LODSB,SHL BX,1,JNC COMP0,JMP NEXT,COMP0:ADD AL,1,NEXT:STOSB,LOOP AGA,MOV AH,4CH,INT 21H,CODE ENDS,END START,例:软件延时程序,试设计要求延时1S的延时程序。,解:利用双重循环实现。子程序如下:,SOFTDLY PROC 指令执行时间(时钟周期数),MOV BL,100 4T,DELAY:MOV CX,n;4T(内循环延时10ms),WAIT:LOOP WAIT;17T或者5T,DEC BL;3T,JNZ DELAY;16T或者4T,RET ;20T,SOFTFDLY ENDP,t内0.0110ms17(n-1)+5+4*T(8088CPU的时钟周期210ns),n=2801(即内循环CX的控制次数),t外(BL)*t内(BL)*19T=100*(t内+19T)1S,4.7.6 子程序结构程序设计,(1)子程序的调用与返回,(2)主程序与子程序间的参数传递。,基本方法有如下3种:,1)子程序的调用与返回,(2)主程序与子程序间的参数传递。,基本方法有如下3种:,寄存器传递参数,堆栈传递参数,存储单元传递参数,(3)主程序和子程序公用的寄存器,主程序与子程序的连接关系,主程序指令,CALL指令下一条指令,子程序指令序列,CALL,(子程序入口),子程序返回,RET,子程序入口,主程序指令,调用,返回,2.子程序嵌套与递归子程序。,一个子程序也可作为主调程序去调用另一个子程序的过程,称为子程序嵌套。,一个子程序作为主调程序去调用自身的过程,称为子程序递归。,(1)子程序嵌套。,(2)递归子程序。,在子程序嵌套情况下,若一个子程序所调用的子程序就是它本身,这种调用称为递归调用,该子程序称为递归子程序。,例:试用寄存器传递参数法编写一个子程序,实现大写字母到小写字母的转换。,解:已知小写英文字母a、b、cx、y、z的ASCII码与大写英文字母A、B、CX、Y、Z的ACSII码相差十六进制常数20H,故要实现转换必须加上20H。,源程序如下:,STATA SEGMENT PARA STACKSTACK,DW 20H DUP(?);,STATA ENDS,DATA SEGMENT,STR1 DB A,BC,DE,A,B,LEN EQU$STR1,STR2 DB LEN DUP(2);用来存放转换后的小写字母。,DATA ENDS,CODE SEGMENT,ASSUME CS:CODE,DS:DATA,SS:STATA,START:MOV AX,DATA,MOV DS,AX,MOV BX,OFFSET STR1,MOV CX,LEN,AGN:MOV AL,BX,CALL SUBR,MOV BX+LEN,AL,LOOP AGN,EXIT:MOV AH,4CH,INT 21H,SUBR PROC NEAR,CMP AL,A,JA EXIT1,CMP AL,,Z,JB EXIT1,ADD AL,20H,EXIT1:RET,SUBR ENDP,CODE ENDS,END START,例:试用堆栈传递参数.编写求某数据区中无符号字数据最大值的子程序及其调用程序.,解:参数通过堆栈传递,子程序存取参数都由BP间址.,源程序如下:,STACK SEGMENT STACKSTACK,DW 32 DUP(0),STACK ENDS,DATA SEGMENT,BUF DW 50,76,88,128,CONT EQU($BUF),/,2,SMAX DW 0,DATA ENDS,CODE SEGMENT,BEGIN PROC FAR,ASSUME CS:CODE,DS:DATA,SS:STACK,PUSH DS,SUB AX,AX,PUSH AX,MOV AX,DATA,MOV DS,AX,MOV AX,OFFSET BUF;,PUSH AX ;入口参数进栈,MOV BX,CONT,PUSH BX,CALL MAX ;调用求最大子程序,POP SMAX ;最大值出栈,送SMAX,RET,BEGIN ENDP,MAX PROC,PUSH BP,MOV BP,SP,PUSH SI,PUSH AX,PUSH BX,PUSH CX,PUSHF,MOV SI,BP+6 ;BUF的偏移地址送SI,MOV CX,BP+4;CONT送CX,MOV BX,SI ;取第一个数据至BX中,DEC CX ;字数据个数减1,MAX1:ADD SI,2 ;指向下一个字数据,MOV AX,SI ;取下一个字数据至AX中,CMP AX,BX,JNA NEXT ;若AX不高于BX则与下一个字数据比较,XCHG AX,BX ;若AX高于BX,则将较大字数据送BX,NEXT:LOOP MAX1,MOVBP+6,BX;最大值存入堆栈,POPF,POP CX,POP BX,POP AX,POP SI,POP BP,RET 2 ;返回后SP指向最大值,MAX ENDP,CODE ENDS,END BEGIN,例:利用存储器传递参数。,设数据段中有两个数组,要求利用存储器传递参数方式编写子程序,对数据段中两个数组分别求和并实现调用。,解:要传递的参数在存储器中,设ARY1和ARY2为字数组,求得的和存入SUM1和SUM2两个字单元。调用前,将数组的偏移地址设置入SI。调用后,运算结果直接由子程序写入到存储器。,源程序如下:,DATA SEGMENT,ARY1 DW 10 DUP(1);定义数组1,SUM1 DW?,ARY2 DW 10 DUP (2);定义数组2,SUM2 DW?,DATA ENDS,STACK SEGMENT PARA STACK STACK,DB 50 DUP(?),STACK ENDS,CODE SEGMENT,ASSUME CS:CODE,DS:DATA,SS:STACK,START:MOV AX,DATA,MOV DS,AX,LEA SI,ARY1 ;数组1首地址,MOV CX,LENGTH ARY1 ;数组1长度,CALL SUM ;调求和子程序,LEA SI,ARY2 ;数组2首地址,MOV CX,LENGTH ARY2 ;数组2长度,CALL SUM ;再调求和子程序,MOV AH,4CH,INT 21H,SUM PROC NEAR ;求和子程序,XOR AX,AX ;AX清零,L1:ADD AX,WORD PTRSI;加数组元素,INC SI,INC SI,LOOP L1,MOV WORD PTRSI,AX;数组和送SUM单元,RET ;子程序返回,SUM ENDP ;子程序结束,CODE ENDS,END START,例:编写计算N!的程序(N0),已知:N!=N*(N-1)*(N-2)*.,N!定义如下:,N!=0!=1 ;当N=0时,N!=,N!=N*(N-1)!(N0);当N0时,解:下面根据递归定义设计该程序。计算N!用子程序实现。,因为N!=N*(N-1)!,所以求(N-1)!必须递归调用计算N!的子程序。由于每次调用使用的参数不同,递归子程序必须保证每次调用都不破坏以前调用时所用的参数和中间结果,所以一般要把每次调用的参数、寄存器的值以及所有的中间结果都存入堆栈。递归子程序是收敛的,因此子程序中要设置基数N=0。当调用参数达到N=0时,有一条件转移指令实现嵌套退出,并返回主程序。,本例设N=2,N!=2!=2(2-1)!=21=2,源程序如下:,DATA SEGMENT,NUM DW 2,RES DW?,DATA ENDS,STACK SEGMENT PARA STACKSTACK,DW 128 DUP(0),STACK ENDS,CODE SEGMENT,MIAN PROC FAR,ASSUME CS:CODE,DS:DATA,SS:STACK,START:PUSH DS,SUB AX,AX,PUSH AX,MOV AX,DATA,MOV DS,AX,MOV AL,NUM,CALL FACT,MOV BX,DX ;BX=DX=0002=21=2!;,RET,MAIN ENDP,FACT PROC,CMP AL,0,JNE NZEO,MOV DL,1,RET,NZE0:PUSH AX,DEC AL,CALL FACT,POP CX,CALL MULT,MOV DX,AX,RET,FACT ENDP,MULT PROC,MOV AL,DL,MUL CL,RET,MULT ENDP,CODE ENDS,END START,4.8 实用程序设计举例,
展开阅读全文