这一节我们要讨论有关FCB的一些较为特殊的应用,主要是三个方面的内容:一是应用FCB删除文件和给文件改名;其二是利用扩展FCB访问具有特殊属性的文件。第三是有关"命令行参数"的问题。我们先来讨论第一个问题--删除与改名。
功能号: 13H
用 途: 删除文件
参 数: DS:DX--指向未打开的FCB
调 用: INT 21H
返 回: AL = 0--文件正确删除
AL = 0FFH--文件未能删除
功能号: 17H
用 途: 文件改名
参 数: DS:DX--指向特殊的FCB
调 用: INT 21H
返 回: AL = 0--文件正确改名
AL = 0FFH--文件未能改名
这两个功能在应用时应注意这样几点:首先要注意它们所使用的FCB的性质,13H功能要求使用一个未打开的FCB,17H功能使用一个特殊的FCB。下面我们就来看看特殊的FCB是一种什么结构,请看图7-4:

可以看到和标准的FCB相比这个新的FCB主要是对偏移11H后作了改进,很显然,既然要改名,总要给出一个新的文件名才行,这个新文件名就填在FCB偏移11H处。第二我们要讨论一下究竟什么文件可以删除。我们平常使用DOS时都知道只读文件或隐含文件是不能删除的,那么使用13H功能删除文件时也要遵守这个规矩。同样,若不使用扩展FCB,那么卷标、子目录也不能用此功能删除,这个功能唯一能删除的就是那些普通的文件。第三,我们平常使用DOS时都知道DEL命令可以一次删除一批文件,也就是使用"*"或"?",我们习惯上称这两个符号为通配符。13H功能同样支持通配符,也就是说你在FCB中填入的文件名可以是"*.*"或"FILE.???"这样的字符串。当然,使用通配符是有条件的,并非所有的DOS版本都支持通配符,2.1版仅支持".",3.0以上版才支持"*"。考虑到现在所使用的DOS版本都在3.3以上,所以大家可以不必判断DOS版本而放心使用通配符。
下面这两个程序演示了这两个功能的使用方法,对于我们平时编制程序来讲,这两个功能其实并不常用,所以大家对它们的用法有些印象也就可以了,不必深究。
DATA SEGMENT
ASSUME DS:DATA
FCB1 LABEL BYTE
DRIVE1 DB 0 ;驱动器号,0:当前 1:A 2:B ...
OLD_NAME DB 'CONFIG ' ;文件原名
OLD_EXT DB 'SYS' ;原扩展名
DB 5 DUP(0)
NEW_NAME DB 'ABCDEFGH' ;新文件名
NEW_EXT DB 'LCS' ;新扩展名
MSG DB 'OK!!!',0DH,0AH,24H
DATA ENDS
CODE SEGMENT
ASSUME CS:CODE
MAIN PROC FAR
MOV AX,DATA
MOV DS,AX
MOV AH,17H ;选择DOS的17H功能
MOV DX,OFFSET FCB1 ;DX指向特殊的FCB
INT 21H ;将文件改名
OR AL,AL ;文件已经改变名字了吗?
JNZ ERR_EXIT ;未能找到指定的文件,转ERR_EXIT
MOV AH,9 ;显示"OK!!!"
MOV DX,OFFSET MSG
INT 21H
ERR_EXIT:
MOV AH,4CH ;结束进程
INT 21H
MAIN ENDP
CODE ENDS
END MAIN
DELFILE.ASM
DATA SEGMENT
ASSUME DS:DATA
FCB2 LABEL BYTE
DRIVE2 DB 0 ;驱动器号,0:当前 1:A 2:B ...
FILE_NAME DB '* ' ;文件名
EXT_NAME DB 'BAK' ;扩展名
CUR_BLOCK2 DW ? ;当前记录块号
REC_SIZE2 DW ? ;记录长度
FILE_SIZE2 DW 2 DUP(?) ;文件长度,由系统填入
CREA_DATE2 DW ? ;建立或最后修改的日期,由系统填入
POSITION2 DB 10 DUP(?) ;保留空间,由系统填入
CUR_REC2 DB ? ;当前记录号
REL_REC2 DW 2 DUP(?) ;相对记录号
MSG DB 'OK!!!',0DH,0AH,24H
DATA ENDS
CODE SEGMENT
ASSUME CS:CODE
MAIN PROC FAR
MOV AX,DATA ;初始化DS寄存器
MOV DS,AX
MOV AH,13H ;选择DOS的13H功能
MOV DX,OFFSET FCB2 ;DX指向未打开的FCB
INT 21H ;删除指定的文件
OR AL,AL ;文件删除了吗?
JNZ ERR_EXIT ;未能找到指定的文件,转ERR_EXIT
MOV AH,9 ;显示"OK!!!"
MOV DX,OFFSET MSG
INT 21H
ERR_EXIT:
MOV AH,4CH ;结束进程
INT 21H
MAIN ENDP
CODE ENDS
END MAIN
我们要讨论的第二个问题是个比较重要的内容,尽管这部分内容也不常用,但它是FCB文件功能与文件句柄功能的一个最显著的区别。我们知道存在于磁盘上的内容不仅是文件,还有子目录和卷标。即使是文件也有只读、隐含等很多种不同的属性。如何处理这些具有属性的文件,这就要用到扩展的FCB。我们前面讨论过有关文件属性的问题,DOS实际上是用一个字节表示文件属性,这个字节存放在扩展FCB的最后,也就是紧挨着驱动器号前面的那个字节。有关这方面的知识请大家复习一下本章的第二节。我准备通过一个实际程序来说明这个问题,请看例程LABEL.ASM
DATA SEGMENT
ASSUME DS:DATA
EXT_FCB LABEL BYTE
DB 0FFH ;扩展FCB标志
DB 5 DUP(0)
DB 00001000B ;属性字节(磁盘卷标)
DRIVE2 DB 0 ;驱动器号,0:当前 1:A 2:B ...
FILE_NAME DB '* ' ;文件名
EXT_NAME DB '* ' ;扩展名
DB 5 DUP(0)
NEW_NAME DB 'ABCDEFGHIJK'
MSG DB 'OK!!!',0DH,0AH,24H
DATA ENDS
CODE SEGMENT
ASSUME CS:CODE
MAIN PROC FAR
MOV AX,DATA ;初始化DS寄存器
MOV DS,AX
MOV AH,17H ;选择文件改名功能
MOV DX,OFFSET EXT_FCB ;DX指向特殊的FCB
INT 21H ;修改磁盘卷标
OR AL,AL ;改名功能执行正确吗?
JNZ ERR_EXIT ;若不正确,转ERR_EXIT
MOV AH,9 ;显示"OK!!!"
MOV DX,OFFSET MSG
INT 21H
ERR_EXIT:
MOV AH,4CH ;结束进程
INT 21H
MAIN ENDP
CODE ENDS
END MAIN
这个小程序可以将当前盘上的卷标改成"ABCDEFGHIJK",请注意我们在扩展FCB中定义的属性字节,其Bit3位为1,这说明我们要改名的是磁盘卷标而非其它的文件。如果将属性字节改成10H,则这个程序可以改子目录名。当然,改子目录名时就不能使用"*.*"了。后面我们还要讲文件句柄功能,那些功能也能处理有属性的文件,但它们都不能完成对卷标和子目录名的操作。