汇编语言与汇编程序.ppt
2.4.1 过程的定义,过程由伪指令PROC和ENDP定义。定义过程的格式为:过程名 PROCNEAR或FAR 过程名 ENDP 其中,PROC和ENDP必须成对出现,且前面都有同一过程名,过程的类型由PROC的操作数指出。若PROC后无操作数,则默认为NEAR类型。,在汇编程序中,可以使用过程定义伪指令定义子程序,通过调用指令CALL调用子程序。过程名是为该子程序起的名字。PROC和ENDP两伪指令之间,是为实现某功能的程序段,其中至少有一条子程序返回指令RET以便返回调用它的程序。,子程序也可以用“:”定义,“:”定义的标号是为该子程序起的名字。主程序把用“:”定义的子程序作为远过程来调用。若子程序与调用它的主程序在同一代码段,则必须用过程来定义该子程序。中断调用都是远调用,所以中断服务子程序用“:”定义。若用过程来定义中断服务子程序定义过程为远过程,而不论他与调用程序是否在不同的代码段。,(1)NEAR属性:调用程序和子程序在同一代码段中(段内调用)(2)FAR属性:调用程序和子程序不在同一代码段中(段间调用),code segment main proc far.call subr1.retmain endpsubr1 proc near.retsubr1 endpcode ends,code segment main proc far.call subr1.retsubr1 proc near.retsubr1 endpmain endpcode ends,例1 调用程序和子程序在同一代码段中,例2 调用程序和子程序不在同一代码段中 sagx segment subt proc far.ret subt endp.call subt.segx ends segy segment.call subt.segy ends,2.4.2 段的定义,段的定义通过SEGMENT和ENDS伪指令进行。定义一个段的格式是:段名 SEGMENT 定位方式 组合方式 类别名 段名 ENDS 其中,SEGMENT和ENDS必须成对出现,它们的前面需有相同的名字,该名字为段名。,例:STACK SEGMENT STACK DW 20DUP(?)STACK ENDS,伪指令SEGMENT有3个可选择的操作数:定位方式,组合方式和类别名。,1.段名 可以用来表示段地址,如取段名为DATA的段地址送AX的指令:MOV AX,DATA 2.组合方式 有NONE、STACK等6种。(1)NONE即无组合方式,表示本段与其他段逻辑上不发生关连,这是隐含的组合方式。,(2)STACK 表示本段与其他模块中的STACK组合方式的同名段组合成一个段。模块中至少有一个STACK段,否则在连接时会有一个错误。定义堆栈段时,必须有组合方式STACK。(3)PUBLIC 表明该段与其他模块中用PUBLIC说明的同名段连接成一个逻辑段,运行时装入同一个物理段中,使用同一个段地址。(其连接顺序由连接命令指定。)(4)COMMON 表明该段与其他模块中由COMMON说明的所有同名段连接时,被重叠放在一起,其长度是同名段中最长者的长度。,3.定位方式有PARA、BYTE、WORD、和PAGE 4种。PARA表示本段要从16的整数倍地址开始,即段首址的最低四位必须为0,这是隐含的定位方式。BYTE表示本段可从任何地址开始。WORD表示本段要从偶地址开始。PAGE表示本段要从256的整数倍地址开始。4.类别名是用单引号括起来的字符串,它是任意的一个名字。连接时LINK将把类别名相同的所有段存放在连续的存储区域中。,2.4.3 汇编地址计数器,汇编地址计数器用符号$表示,它用来记录正在被汇编程序汇编的指令的地址,即它的内容标出了汇编程序当前的工作位置。汇编程序为每个段分配一个汇编地址计数器。对需要分配存储单元的变量和产生目标代码的指令,$就按存储单元数和目标代码的长度增值。因此,段内定义的所有标号和变量的偏移地址就是当前值。,DATA SEGMENTBUF DB 0123456789ABCDEFCOUNT EQU$-BUFDATA ENDS 常量COUNT的值就是变量BUF数据区所占的存储单元数16。,$可以用作指令的操作数,此时$的值就是该指令的偏移地址。$也可以出现在表达式中。如:,$的值可以用伪指令ORG来设置。其格式是:ORG 数值表达式 功能是将$设置成数值表达式的值(0000HFFFFH之间的整数)。e.g ORG$+8,2.4.4 段寄存器的假定,存储单元的段地址来自某个段寄存器。源程序在代码段的开始就要对段寄存器与段之间的关系作假定,以便宏汇编程序MASM汇编时根据指令给定的偏移地址和段寄存器中的段地址计算出正确的物理地址。段寄存器与段的关系,由伪指令ASSUME设定,设定格式是:ASSUME SREG:SNAM,SREG:SNAM,其中SREG为4个段寄存器CS、SS、DS、ES中的任一个,SNAM是段名。,需要说明的是,伪指令ASSUME只是将段寄存器与段间的对应关系告诉汇编程序,它并没有将段首址置入对应的段寄存器中,这一工作要到程序最后投入运行时才能完成。那时系统自动将代码段和堆栈段的段首址分别置入CS和SS,将PSP(program segment prefix)的段首址同时置入DS和ES。因此CS和SS不用程序处理;但对DS和ES,则必须由程序将其段首址分别置入。,例如:CODE SEGMENT ASSUME CS:CODE,DS:DATA,SS:STACK MOV AX,DATA MOV DS,AX CODE ENDS,2.4.5 源程序的结束,源程序的结束要用伪指令END,其格式是:END表达式 该伪指令用在源程序的最后,用以表示整个源程序的结束,即告诉汇编程序,汇编工作到此结束。其中可选项表达式的值必须是存储器的地址,该地址即为程序的启动地址,亦就是程序的第一条可执行指令的地址。表达式一般为过程名。如果不带表达式,则该程序不能单独运行,只是供其他程序调用的子模块。,2.4.6 宏汇编源程序的格式,宏汇编源程序一般由3个段组成,其格式如下:stack segment stack stack dw 32 dup(?)stack endsdata segmentdata endscode segmentbegin proc far assume ss:stack,cs:code,ds:data,push ds sub ax,ax push ax mov ax,data mov ds,ax retbegin endpcode ends end begin,一个基本的汇编语言程序框架如下:stack SEGMENT PARA stack DB 100 DUP(stack)stack ENDS data SEGMENT data ENDS code SEGMENT ASSUME CS:code,DS:data,ES:data start:MOV AX,data MOV DS,AX MOV ES,AX MOV AL,4CH INT 21H code ENDS END start,堆栈段,数据段,代码段,在DOS状态下,执行EXE程序时,DOS会在COMMAND.COM暂存部分之后建立一个256字节的程序段前缀PSP(program segment prefix),在其后装入EXE程序,并把控制权转移给它。在PSP的首地址处有一条INT 20H指令。,DOS在转移控制权时,将CS指向EXE程序的代码段,SS指向堆栈段,DS和ES并不指向用户程序的数据段和附加数据段而是指向PSP,这样便于用户使用和处理PSP中的信息。所以在初始化程序中有将数据段的段地址送DS的两条指令(若有附加数据段,还应有将附加段的段地址送ES的指令):MOV AX,DATA MOV DS,AX DOS像调用子程序一样,调用EXE程序,EXE程序执行后也应像子程序返回调用程序一样返回DOS。,DOS为EXE程序返回DOS安排了两种方法:(1)用调用号为4CH的系统功能调用(2)用软中断指令 INT 20H。4CH功能调用返回DOS虽简单,但不论是什么程序调用它均返回DOS。软中断INT 20H是返回调用程序。INT 20H返回调用程序要求CS指向PSP。只能利用远过程中的返回指令能将堆栈中的PSP的首地址送给CS和IP,然后执行放在PSP首地址中的INT 20H指令,从而使EXE程序结束返回调用程序。程序段为:,PUSH DS;PSP的段地址进栈 SUB AX,AX PUSH AX;PSP首偏移地址进栈 RET;PSP的首地址出栈 综上述可知,执行初始化程序的作用其一是使PSP的首地址进栈,以便远返回指令结束用户程序返回调用程序,其二是使DS指向数据段的段首址。,2.5 常用系统功能调用,IBM PC微机系统为汇编用户提供了两个程序接口。一个是DOS系统功能调用,另一个是ROM中的BIOS(basic input/output system)。系统功能调用和BIOS由一系列的服务子程序构成,但调用与返回不是使用子程序调用指令CALL和返回指令RET,而是通过软中断指令INT N和中断返回指令IRET调用和返回。我们仅介绍DOS系统功能调用。,层次特点:ROM BIOS中的中断子程 使用IN/OUT指令直接控制外设,实现与外设之间的输入/输出操作,以软件形式向其上层提供服务。IO.SYS中的中断子程(称基本输入/输出BIOS模块)调用ROM BIOS的基本I/O功能,向 MSDOS.SYS提供设备驱动服务。,MSDOS.SYS中的中断子程(称DOS内核模块)调用IO.SYS,实现对外设的控制。与标准外设有两层隔离:IO.SYS和ROM BIOS。其中21H类型的中断子程提供了丰富的系统服务,称21类型的中断调用为DOS系统(功能)调用。,用户编程原则尽可能使用DOS的系统功能调用,提高程序可移植性。在DOS功能不能实现情况下,考虑用BIOS功能调用。在DOS和BIOS的中断子程 不能解决问题时,使用IN/OUT指令直接控制硬件。,2.5.1 系统功能调用,系统功能调用是IBM PC微机系统为汇编用户提供的一个程序接口。系统功能调用共有4类。我们仅介绍设备管理系统功能调用中基本的I/O管理功能。使用系统功能调用的一般过程为:把调用号放入AH中,设置入口参数,然后执行INT 21H指令,最后分析处理出口参数。键盘和显示器的DOS功能调用如表2-3所列。本节仅介绍常用的1、2、9、10等4个系统功能调用。,调用方法,1.1号功能调用 MOV AH,1 INT 21H 执行该调用时将等待键入,一旦有键按下就将该按键字符的ASCII码读入AL,并同时显示该字符。2.2号功能调用 MOV DL,待显示字符的ASCII码 MOV AH,2 INT 21H 本调用执行后,显示器显示待显示的字符。,3.9号功能调用 MOV DX,待显示字符串的首偏移地址 MOV AH,9 INT 21H 本调用执行后,显示器显示待显示的字符串。执行前要在DS数据段定义一以$结尾的字符串。当需要输出数据区中某一字符串时,若该字符串的尾部无$,一定要在其尾部置入一个$;若该字符串中间就有$,则要采用2号功能调用逐个输出该字符串中的字符。,4.10号功能调用 MOV DX,数据区的首偏移地址 MOV AH,10 INT 21H 当需要输入字符串时,应在DS数据段中事先定义一个变量数据区IBUF,其定义格式如下:IBUF DB 数据区大小,?,数据区大小 DUP(?)其中:数据区大小是一个无符号数(2255)。执行该调用时将等待键入1254个字符,键入的字符数可以少不能多,最后以回车结束本调用。,DUP(?)前的“数据区大小”应与前面一个“数据区大小”一致,因为数据区的大小是由前面的即第1个单元规定的,从第3个单元开始是预留给10号功能调用装载键入字符的,留多了不能多装,是浪费;留少了可多装,当输入的字符数超过预留的单元数时,数据区就会自动往下延伸,冲掉紧跟其后的存储单元中的内容,造成程序运行的混乱。第2个单元是预留给装载10号功能调用时实际键入字符数的,实际键入的字符数不包括回车(0DH)。,最后,要特别强调的是:2号功能调用、9号功能调用和10号功能调用虽然未使用AL,但调用后也会破坏AL中原来的内容。为防止AL中原来的内容被破坏,在调用前应先保护AL,调用后再恢复。,2.5.2 功能调用应用举例,例2.5 编写汇编语言源程序,在显示器上显示wish you success!。只需将欲显示字符串的ASCII码存放到字节变量数据区中(字节变量数据区一定要以$结束),用9号功能调用即可显示该字符串。程序如下:OBF DB wish you success!$MOV DX,OFFSET OBF MOV AH,9 INT 21H,例2.6 将键入的4位十进制数(如5,则键入0005)以压缩BCD数形式存入字变量SW中。程序如下:,IBUF DB 5,0,5 DUP(?)MOV DX,OFFSET IBUF;10号功能调用 MOV AH,10 INT 21H MOV AX,WORD PTR IBUF+4;键入数的个位和十位送AX AND AX,0F0FH;ASCII码变非压缩BCD数 MOV CL,4 SHL AL,CL;将10位移至AL的高4位 OR AL,AH;将10位和个位拼合在AL中 MOV BYTE PTR SW,AL;存BCD数字的十位和个位,MOV AX,WORD PTR IBUF+2;键入数的百位和千位送AX AND AX,0F0FH;ASCII码变非压缩BCD数 SHL AL,CL;将千位移至AL的高4位 OR AL,AH;千位和百位拼合在AL中 MOV BYTE PTR SW+1,AL;存千位和百位,例2.7 镜子程序。“镜子”程序的功能是接收并回显键盘输入的一串字符,然后在下一行再将该串字符显示出来。可见该功能主要由10号功能调用和9号功能调用来完成。根据10号功能调用的入口参数,在数据段定义了字节变量IBUF。第1个单元是允许键入字符数FFH,即最多可接收除回车外的254个任意字符和一个回车;第2单元是预留装载实际键入字符个数的;从第3单元开始是预留装载键入字符的。,10号功能调用结束后,只要把字符$放入存放回车的单元,即可使用9号功能调用把自IBUF+2单元开始的字符送显示器显示。镜子程序如下:OBUF DB,0DH,0AH,$IBUF DB 0FFH,0,255 DUP(?),MOV DX,OFFSET OBUF;显示“”,回车,换行 MOV AH,9 INT 21H MOV DX,OFFSET IBUF;键入并显示字符串 MOV AH,10 INT 21H,MOV BL,IBUF+1;取得实际键入的字符串长度 MOV BH,0 MOV IBUF BX+2,$;将$送字符串后 MOV DL,0AH;换行 MOV AH,2 INT 21H MOV DX,OFFSET IBUF+2;再显示键入的字符串 MOV AH,9 INT 21H,关于汇编语言,Assemble Language,一种面向机器的程序设计语言,是一种用符号表示的低级程序设计语言(机器语言的符号化描述),通常是为特定计算机或计算机系列专门设计的。,Assemble Language,用汇编语言编写的程序不能由机器直接执行,而必须经汇编程序翻译成机器语言程序。汇编语言指令与翻译成的汇编过程示意:,采用汇编语言进行程序设计的优点,可充分利用机器的硬件功能和结构特点,加快程序的执行速度,减少目标程序所占用的存储空间常用来编写实时控制程序、实时通信程序,有时也用来编制某些系统软件程序。,缺点:,编程效率低(与人们描述计算过程的需要差距大)与机器硬件的具体结构联系过于紧密在一种结构的机器上开发的程序极难移植到另一种不同结构的机器上去。,汇编语言程序的简历及汇编过程,检查源程序;测出源程序中的语法错误,并给出出错信息;产生目标文件(.OBJ),并可给出列表文件(同时列出汇编语言源程序和机器语言目标程序的文件,称之为.LST文件)和交叉索引文件(列出程序中使用的符号、变量和标号以及引用情况,称之为.CRF文件)。展开宏指令。,汇编示意图,汇编程序的主要功能,汇编程序分两种,一种是基本汇编(ASM.EXE),一种是宏汇编(MASM.EXE),宏汇编功能比较强。,连接程序,汇编之后生成的OBJ文件必须经过链接过程,才能成为扩展名.EXE的可执行文件。链接的过程就是调用连接程序(LINK.EXE),对OBJ文件进行定位、链接,最后生成扩展名为EXE的可执行文件。如果需要,也可生成MAP文件和LIB文件。,连接示意图:,调试程序(DEBUG.COM),DEBUG PROG.EXE-U 起始地址 结束地址(反汇编)-G=起始地址 断点地址-T=地址(可选执行指令的条数)-D 显示存储单元的内容-E 修改存储单元的内容-Q 退出 DEBUG,