2010 发信人: wain (北斗星), 信区: CS标 题: 浅谈如何在汇编程序中实现正常退出发信站: 听音小筑 (2001年10月14日21:28:55 星期天), 站内信件【论文题目】浅谈如何在汇编程序中实现正常退出【单位】 天津大学计算机系 95 软件乙班【作者】 李罡【内容摘要】本文的主要内容是在汇编语言的程序中实现正常退出的两种方法,即中断法和返回指令法。本文着重谈到利用 INT 20H 及 21H 中 00H、 31H、27H 实现程序退出的方法,以及使用 ret 指令返回的注意事项,力求使大家知其然而且知其所以然。本文为作者在学习汇编语言中遇到的问题以及为了解决问题而实践查阅资料总结出的。草写成文,以求指正。浅谈如何在汇编程序中实现正常退出众所周知,汇编语言是一种低级语言。要在 DOS 级上处理 MS-DOS ,没有一种高级语言能完全胜任这项工作。要想充分利用你的操作系统,则应直接在机器级别上编程,这就需要汇编语言。对于学习者来说,学习一门高级语言,如 BASIC、PASCAL 或C后,就应该着手学习汇编语言,使自己的编程水平提高一个台阶。初学 8086汇编语言的人,大概第一个遇到的问题就是编的汇编程序如何退出。我们知道,高级语言不需要考虑专门编写退出语句,编译系统会自动为程序加上结束进程、返回 DOS 的控制语句的,可汇编语言并不是这样,如你的程序在结束工作后没有退出语句,CPU 将不知何去何从,必“死”无疑。一般来说,退出一个程序有两种办法,一是利用中断,二是利用 ret 语句返回。首先谈谈利用中断。INT 20H 是 DOS 的程序结束中断。比如下面一个程序:; segmentassume cs:csegstart: org 100h.. ;程序体.int 20hcseg endsend start这个结构看起来没什么问题,用 masm 或 tasm 生成 ,再用link 或tlink 生成 ,一运行,准死机。这是为什么呢?查看《DOS/BIOS 使用详解》,对 INT 20H 的说明为“该功能调用与 DOS 功能调用00H 完成的操作相同。它使当前进程终止,并将控制权返回到它的父进程。”它的入口参数要求 CS 指向程序的 PSP 的段地址。原来问题出在这儿。用tlink 生成 ,再运行,正常退出。原来,这涉及到 COM 与 EXE 都是 DOS 下可执行文件,其区别为 COM 文件比较紧凑,整个程序限定在 64K 中,结构为:偏移地址 0000 到 0100 放的是程序的 PSP,所谓 PSP,指的是程序段前缀,对于所有的.com和.exe程序,包括 TSR 在内,DOS 都要设置称为 PSP 的 256 字节区。PSP 是一种前缀,它在内存程序的前面。内容为程序运行时必需的数据和缓冲区。PSP 后为程序主体,从低向高放程序数据、代码、附加段内容(这三个段顺序依程序设计而定),从高(偏移地址00FE)向低入程序的堆栈区,整个程序中 CS=DS=ES=SS ,CS 不必再设,自然指向PSP段地址(即程序所在段),所以能用INT 20H 退出。而 exe 程序则比较复杂,需要程序重定位,一般而言各段寄存器地址不全相同,其中 DS 和 ES 指向 PSP,而 CS 则比 DS 大。例如 ,若用debug 载入:c:>debug 显然,PSP 段址为 0FB5,而 cs 指向 0FC5 ,故 INT 20H 不能正常退出。对于.exe的退出,应该采用 Microsoft 推荐的 DOS 调用 4CH 子功能,即将 中的 int 20h 换为下面两句:mov ah,4chint 21h因为 4CH 子功能不要求入口地址,且可用 AL 返回终止代码。用 4CH 可以安全退出.exe和.com,值得推荐使用。以上是不驻留退出,对下 TSR (常驻内存程序)其退出可采用 INT 27H 或INT 21H 的 31H 号子功能,其入口参数为 DX 指向程序常驻部分的底部,然后调用中断,这里不再详述。对于用 ret 语句返回,要求以下的格式:; segmentmain proc farassume cs:csegstart: push ds ;初始化堆栈底xor ax,axpush ax.. ;程序体.retmain endpcseg endsend start我们知道,ret 语句用于结束过程,返回父进程。对于主进程而言,其父进程即为DOS,是 DOS 调用它并执行的,这种调用是远调用,所以 main 过程为 far,可开头三句初始化是什么意思呢?我们知道,ret 语句实际上是从堆栈中取出两个字,分别赋给 ip 和 cs ,堆栈底放的即为父进程的返回地址,这样即实现返回。观察前三句初始化语句实际是把 ds 值和 0000 推入栈中,(xor ax,ax 是 ax 自身异或,实际上即将 ax 赋0)这样返回时将0000 赋给 ip ,把程序开始时的 ds 值还给 cs ,实现返回DOS ,这是为什么呢?我们开头讲过,程序开始时 ds 指向 PSP 区,而 PSP 区的前二个字节放的即为返回指令,籍此实现返回。综上所述,返回可以有两种办法:中断法和 ret语句法。中断中可用的是20h、27h和 21h 中的 00h 、31h、4ch 子功能。其中 20h 和 21h 中断的 00h 子功能不加处理不能直接用于.exe的返回。INT 27H 和 21H 的 31h 用于驻留返回,其余的用于非驻留退出。用 ret 语句要先进行堆栈初始化方可。了解以上知识,可以避免在学习汇编语言中走弯路,为进一步学习汇编语言开个好头。This entry was posted on 星期四, 二月 4th, 2010 at 6:48 上午 and is filed under 未分类. You can follow any responses to this entry through the RSS feed. You can leave a response, or trackback from your own site. Your Reply点击这里取消回复 Name (required) Mail (will not be published) (required) WebsitePages关于我 Archives2010年三月 2010年二月 Categories未分类 (11) --------------------------------------------------------------------------------北斗星文轩 by Themebuilder | Entries (RSS) and Comments (RSS).