了解和掌握PSP中的信息分布就是为了利用其信息。对于EXE文件,可用中断21H之功能51H获取其段地址。如:
MOVAH, 51H
INT21H;BX=PSP的段地址
MOV ES, BX
CMP byte ptr ES:[80H], 0;检查PSP的长度
JEnext
…
对于COM文件,因为其只有一个段,所以,可用更简单的方式来检查PSP的内容。
MOV BX, 80H
CMPbyte ptr [BX], 0;检查PSP的长度
JEnext
…
例10.17 利用PSP中的信息来终止当前程序的运行。
解:
DSEGSEGMENT
MSG DB "Hello$"
DSEGENDS
CSEGSEGMENT ’CODE’
ASSUME CS:CSEG, DS:DSEG
MAINPROC FAR
start:;在装入
内存时,DS存放的是PSP的段地址
PUSHDS
XORAX, AX
PUSHAX;当前堆栈内容为0和PSP的段地址
MOVAX, DSEG
MOVDS, AX
MOVDX, OFFSET MSG
MOVAH, 9
INT21H
RET
MAINENDP
CSEGENDS
END start
例10.17是早期利用PSP来终止程序的方法。子程序MAIN必须定义为FAR类型,其前三条语句是为用PSP的头二个字节来终止程序运行服务的,但现在通常用中断21H之功能4CH来终止程序的运行。
例10.18 编写程序,显示其命令行参数信息。
解:在使用命令行时,操作系统允许在被装入的程序名之后附加多达127个字符(包括最后的回车符)作为其命令的参数。
本例子的目的就是要了解命令行参数的存储方法,为以后使用命令行参数作准备。
.MODEL SMALL
.CODE
.STARTUP
MOVAH, 51H
INT21H
MOV DS, BX;DS=PSP的段地址
MOVBX, 80H
MOV CL, [BX]
XOR CH, CH
JCXZ over
INC BX;80~FFH字段中的跳过第二个字节
.REPEAT
INCBX
MOVDL, [BX]
MOVAH, 2
INT21H
.UNTILCXZ;显示命令行参数中的字符
over:
.EXIT 0
END
例10.19 编写一个类型于
DOS内部命令TYPE的程序,该命令的使用方法如下:
……>type 文件1,文件2,…
其功能是分别显示其参数文件1、文件2等内容,在显示文件内容前先显示文件名。显示完内容后,暂停,等待用户按任意键。若某文件不存在,则显示相应的提示信息。
解:为了较好地解答本题,我们可以对该问题按以下步骤来解决:
1、若命令行参数中的字符数为0,则结束本程序的运行;
2、从命令行参数中分离出一个文件名;
3、调用子程序,显示当前文件名、文件内容和等待用户按键;
4、重复步骤1~3,直到所有参数被处理完。
.MODEL SMALL, C
.DATA
FileDB 14 DUP(’ ’)
Buff DB 128 DUP(0)
Msg1DB 0DH, 0AH, "$"
Msg2DB "Not Found$"
Msg3DB "Press any key...$"
.CODE
;显示字符串MSG后,再进行回车、换行
DispStrPROC USES AX DX, MSG:PTR BYTE
MOVDX, MSG;显示指定的信息
MOVAH, 09H
INT21H
LEADX, Msg1;显示回车、换行
MOVAH, 09H
INT21H
RET
DispStrENDP
;文件名的长度为传递参数Len。若文件不存在,则显示提示信息,否则,显示文件内容;
;完成上述操作后,等待用户按键
DispPROC USES AX BX CX DX, Len:BYTE
XORBX, BX
MOVBL, Len
MOVFile[BX], ’$’
INVOKEDispStr, ADDR File;显示文件名
MOVFile[BX],0
LEADX, File
MOVAL, 0H
MOVAH, 3DH
INT21H
.IF CARRY?;若创建失败,则显示失败信息
INVOKE DispStr, ADDR Msg2
JMPover1
.ENDIF
MOVBX, AX;参见例8.14中的有关说明
read:
LEADX, Buff
MOVCX, 128
MOVAH, 3FH
INT21H
.IF CARRY? || AX==0
JZclose
.ENDIF
PUSHBX
LEADX, Buff
MOVCX, AX
MOVBX, 1
MOVAH, 40H
INT21H
POPBX
JMPread
close:
MOVAH, 3EH;关闭已打开的文件
INT21H
over1:
INVOKEDispStr, ADDR Msg3;显示等待用户按键提示信息
MOVAH, 07H
INT21H;等待用户按键
RET
DispENDP
.STARTUP
MOVAH, 51H
INT21H
MOVES, BX
MOVBX, 80H
MOVCL, ES:[BX]
DECCL
INCBX
.WHILE CL>0;CL=未被处理的参数字符数
XORAL, AL;记录文件名的长度
LEADI, File
.REPEAT
INCBX
MOVAH, ES:[BX]
DECCL
.BREAK .IF AH==’,’
MOV[DI], AH;从参数中分离出字符,存入文件名中
INCDI
INCAL
.UNTILCL==0
INVOKEDisp, AL;处理当前分离出来的文件名
.ENDW
.EXIT 0
END