第5章汇编语言程序设计本章内容提要5.1汇编语言程序的编辑、汇编、连接和调试5.2汇编语言入门5.3汇编程序设计的基本方法5.4高级汇编程序设计5.1汇编语言程序的编辑、汇编、连接和调试源程序编辑器EDIT.ASM源程序文件汇编程序MASM.OBJ目标程序文件连接程序LINK.EXE可执行文件.LST列表文件.CRF交叉引用文件.MAP映像文件.LIB库文件实训5-1显示26个小写英文字母要想将26个小写英文字母在屏幕上显示出来,首先将第一个小写英文字母a的ASCII码值存入存储单元A,然后通过一个循环,将26个字母逐个显示出来。为此,我们应预先设置循环次数(即字母个数),每执行一次循环,A中的值(即要显示字符对应的ASCII码值)都应增加1。源程序DSEGSEGMENT;数据段,定义变量,分配存储空间ADB97DDSEGENDSSSEGSEGMENTSTACK;堆栈段DB100DUP(?)SSEGENDSCSEGSEGMENT;代码段ASSUMECS:CSEG,DS:DSEG,SS:SSEGSTART:MOVAX,DSEG;给数据段寄存器装初值MOVDS,AXMOVCX,26D;将循环计数值存入CXMOVDL,a;将字母a的ASCII码存入DLNEXT:MOVAH,02H;显示字符INT21HINCA;A中的值加1MOVDL,ALOOPNEXT;执行循环MOVAH,4CH;系统功能调用,结束程序返回DOSINT21HCSEGENDSENDSTART5.2汇编语言入门5.2.1汇编语言概述采用字母、符号等来表示机器指令的二进制代码,这就是汇编语言。用汇编语言编写的程序称为汇编语言源程序。将汇编语言源程序翻译成机器语言的过程称为汇编。5.2.2汇编语言中的助记符1.指令助记符2.伪指令助记符3.其他助记符如标号、常量、变量和表达式等汇编时不产生机器码,也不产生任何操作汇编时被转换成二进制的指令代码,每一条指令代码都对应着CPU的一种操作使CPU产生动作、并在程序执行时才处理的语句,就是第3章学习的处理器指令。不使CPU产生动作、在程序执行前由汇编程序处理的说明性语句,例如,数据说明、变量定义等等。5.2.3汇编语言的语句格式指令语句的格式为[标号:]指令助记符[操作数,操作数][;注释]伪指令语句的格式为[名字]伪指令助记符[操作数,…,操作数][;注释]相同点:(1)标号和名字(2)助记符(3)操作数(4)注释各部分之间至少要用一个空格作为间隔。不同点:在形式上:带不带冒号,是否可转向它在本质上:汇编时能否形成对应的机器码5.2.4汇编语言的常数和表达式1.常数2.表达式汇编语言中的表达式分为数字表达式和地址表达式两种。数值常数字符串常数表达式是由操作数和运算符组成的。表达式中的运算符例如,LEASI,COUNT+5MOVAL,0ABHAND0FHMOVAX,NUMGT1005.2.5汇编语言的标号和变量1.标号2.变量标号的属性:段地址、偏移地址、类型标号是指令语句的标识符,用来表示该指令所在内存单元的地址。变量主要用来定义存放在存储单元中的数据。变量的定义格式为:变量名DB表达式;定义字节变量变量名DW表达式;定义字变量变量名DD表达式;定义双字变量变量名DQ表达式;定义8字节变量变量名DT表达式;定义10字节变量变量的属性:段地址、偏移地址、类型、长度、大小11标号:是一条指令语句的符号地址。在汇编源程序中,只有在需要转向一条指令语句时,才为该指令语句设置标号,以便在转移类指令(含子程序调用指令)中直接引用这个标号。因此,标号可作为转移类指令的操作数,即转移地址。标号的三种属性:①段值:所在段的段地址,总是在CS段寄存器中;②偏移量:与变量相同,所在段的段内偏移地址;③类型:分NEAR和FAR两种。NEAR—表示标号所在语句与转移指令或调用指令在同一码段内,只需改变IP即可。FAR—标号所在语句与转移指令或调用指令不在同一码段内。若没有对类型进行说明,默认为NEAR。12变量:表示数据初值表中第一个数据的偏移地址,在程序中作为存储器操作数使用,变量名由用户自定义。如前面例子中的BLOCK、BUF等,一般在数据段中定义。由于汇编语言中存储单元是分段使用的,所以变量具有三种属性:①段值—变量定义所在段的段地址。②偏移量—变量所指的单元地址与段起始地址之间的位移量③类型—有字节(byte)、字(word)和双字(doubleword)等。提示:每一个变量定义后都具有此三种属性,设置变量名是为了方便存取它指示的存储单元。13例:测试为0或1若要检测AL中的最低位是否为1,若为1则转移。testal,01h;测试AL的最低位D0jnznext;标志ZF=0,即D0=1;则程序转移到there...;否则ZF=1,即D0=0,顺序执行next:...5.2.6汇编语言的属性运算符表达式名称格式功能取地址运算符SEG变量或标号返回变量或标号的段地址取偏移地址运算符OFFSET变量或标号返回变量或标号的偏移地址取类型运算符TYPE变量或标号返回变量或标号的类型值取变量长度运算符LENGTH变量返回变量的长度(即变量中元素的个数)取变量总字节数运算符SIZE变量返回变量所包含的总字节数例如,MOVAX,SEGCOUNTMOVSI,OFFSETCOUNTMOVAX,TYPECOUNTCOUNTDW100DUP(1),LENGTHCOUNTBUFFDD1,2,3,LENGTHBUFFCOUNTDW100DUP(1),SIZECOUNT5.2.6汇编语言的属性运算符表达式名称格式功能类型运算符类型PTR变量、标号或表达式对已定义的变量、标号或表达式,临时转换其类型类型定义运算符变量或标号EQUTHIS类型指定变量或标号的类型段超越前缀段寄存器名:变量、标号或地址表达式给变量、标号或地址表达式临时指定一个段属性取高字节运算符HIGH变量或标号分离出变量或标号对应的运算对象的高字节取低字节运算符LOW变量或标号分离出变量或标号对应的运算对象的低字节短转移运算符SHORT标号说明转移指令中的转移为短转移例如,MOVAX,WORDPTRCOUNTCOUNTEQUTHISBYTEMOVAX,ES:[1000H]DATAEQU1234H,MOVAL,HIGHDATADATAEQU1234H,MOVAL,LOWDATA5.2.7常用伪指令1.数据定义伪指令格式:变量数据定义伪指令表达式功能:为数据分配存储单元常用数据定义伪指令【例5-1】数据段DSEG由以下语句组成:DSEGSEGMENTNUM1DB12HNUM2DB34H,56H,78HNUM3DB?DSEGENDS设本段的段基址为1000H内存单元分配情况【例5-2】COUNTDW1122H,3344H的内存单元分配情况【例5-3】DB100DUP(?)的功能是:分配100个字节的内存单元。【例5-4】DATADB'ABCD'的内存单元分配情况2.符号定义伪指令格式:标识符EQU表达式功能:用一个标识符来表示表达式的值,但并不为其分配内存单元赋值伪指令例如,COUNTEQU10NUMEQUTAB[BX+3]格式:标识符=表达式功能:与EQU的功能相同,但“=”可以对同一标识符进行重新定义等号伪指令例如,COUNT=10COUNT=COUNT+1格式:变量或标号LABEL类型功能:定义或修改变量或标号的类型标号定义伪指令例如,COUNTLABELBYTEDB103.段定义伪指令格式:段名SEGMENT[定位类型][组合类型][类别]……段名ENDS功能:对段的结构进行定义SEGMENT和ENDS伪指令格式:ASSUME段寄存器:段名[,…,段寄存器:段名]功能:指明段寄存器与各段之间的对应关系ASSUME伪指令例如,ASSUMECS:CSEG,DS:DSEG,SS:SSEG4.过程定义伪指令格式:过程名PROC[类型]……RET过程名ENDP功能:标识一个执行特定功能的代码块(又称为子程序)5.结束伪指令格式:END[标号]功能:汇编程序结束5.2.8汇编语言源程序的结构汇编语言源程序的基本框架实训5-2统计一组数据中正数、零和负数的个数统计一组数据中正数、零和负数的个数,并将负数的个数在屏幕上显示出来。源程序DSEGSEGMENT;数据段,给变量指定数据,分配存储空间ARRAYDB5,3,-4,0,-5,-3;定义一个数组NUMDB0,0,0;NUM中用于存放正数、零和负数的个数DSEGENDSSSEGSEGMENT;堆栈段DB100DUP(0)SSEGENDSCSEGSEGMENT;代码段ASSUMECS:CSEG,DS:DSEG,SS:SSEGSTART:MOVAX,DSEG;将数据段基址装入数据段寄存器MOVDS,AXMOVSI,0;将SI的初值置为0CALLCOUNT;调用COUNT子程序ADDNUM[2],30H;将负数的个数转换为ASCII码MOVDL,NUM[2];DOS功能调用,显示负数的个数MOVAH,02HINT21HMOVAH,4CH;系统功能调用,结束程序返回DOSINT21HCOUNTPROCNEAR;COUNT过程MOVCX,6;将循环的次数送入CXLOP:CMPARRAY[SI],0;将数组中的各元素与0比较JZZERO;结果为0时转移到ZERO处JNSZHENG;结果为正时转移到ZHENG处ADDNUM[2],1;统计负数的个数JMPNEXT;转移到NEXT处ZERO:ADDNUM[1],1;统计0的个数JMPNEXTZHENG:ADDNUM,1;统计正数的个数NEXT:INCSI;SI的内容加1LOOPLOP;执行循环RET;返回子程序调用处COUNTENDPCSEGENDSENDSTART5.3汇编程序设计的基本方法5.3.1汇编程序设计的一般步骤1.分析问题,确定算法2.画出程序流程图起止框处理框判断框连接框流程线3.编写源程序4.调试程序5.3.2顺序结构程序设计程序设计的基本方法有三种,分别是:顺序结构程序设计方法、分支结构程序设计方法和循环结构程序设计方法。顺序结构是最简单、最基本的程序结构,它是按照指令在程序中排列的先后顺序逐条执行的。顺序结构程序的流程图中只有一个起始框和一个结束框。5.3.3分支结构程序设计1.双分支结构IFTHEN结构IFTHENELSE结构2.多分支结构CASE结构3.跳转表在内存的一个连续区域中,依次存放完成各功能的分支子程序的首地址,构成一个跳转表。通过计算存储单元的偏移地址,获得对应的分支子程序的首地址,从而转去执行对应的子程序。实训5-3求三个有符号数中的最大数比较三个有符号数X、Y和Z的大小,并将最大的那个数存入MAX所在的存储单元中。程序流程图源程序DSEGSEGMENT;数据段,定义变量XDB12HYDB-3ZDB15MAXDB?DSEGENDSSSEGSEGMENTSTACK;堆栈段DB100DUP(?)SSEGENDSCSEGSEGMENT;代码段ASSUMECS:CSEG,DS:DSEG,SS:SSEGSTART:MOVAX,DSEG;将数据段基址装入数据段寄存器MOVDS,AXMOVAL,X;将X送入ALCMPAL,Y;比较X和Y大小JGF1;如果XY,则程序转移至F1MOVAL,Y;如果X≤Y,将Y送入ALF1:CMPAL,Z;比较AL中的内容和Z大小JGF3;如果(AL)Z,则程序转移至F3F2:MOVAL,Z;将(AL)≤Z,将Z送入ALF3:MOVMAX,AL;将最大值AL送入MAXMOVAH,4CH;系统功能调用,结束程序返回DOSINT21HCSEGENDSENDSTART5.3.4循环结构程序设计1.循环结构程序的基本构成初始化部分循环体部分修改部分循环控制部分结束部分2.循环程序的结构形式3.循环结构程序的分类按照循环控制方式分:计数控制循环条件控制循环按照循环嵌套的层次分:单重循环多重循环实训5-4冒泡排序法对以DAT