我需要使用Int 21h / function 23h获取文件大小。我不知道FCB是如何工作的,也不知道如何使用它。此documentation中给出的函数23h的描述是:
功能23h(35)使用FCB获取文件大小
Returns the number of records in a file. On entry: AH 23h DS:DX Pointer to an unopened FCB Returns: AL 00h If matching file found FFh If no matching file found
我想如何使用它?
答案 0 :(得分:2)
您链接的同一页面底部有FCB的链接。如果您遵循它,您将看到您需要为FCB初始化一块内存,并使用驱动器号(03代表C :),8.3格式的文件名以及其他几个字段填充它。将ds:dx指向该内存块,将ah设置为23h,int 21
。如果al为0,则表示成功,您可以从ds:dx + 10h获取文件长度。
请参阅偏移量为0x10的b2 6a 00 00
,它与指定文件的大小相匹配:
jcomeau@aspire:/tmp$ ls -l /usr/src/dosdebug/DEBUG.TXT
-rw-r--r-- 1 jcomeau jcomeau 27314 Feb 15 2014 /usr/src/dosdebug/DEBUG.TXT
jcomeau@aspire:/tmp$ printf '%x\n' 27314
6ab2
我必须修补dosbox中的一个错误才能使其正常工作,因此更新速度很慢。
diff -up ./include/dos_inc.h.orig ./include/dos_inc.h
--- ./include/dos_inc.h.orig 2015-12-27 12:43:12.000000000 -0800
+++ ./include/dos_inc.h 2015-12-27 11:53:19.000000000 -0800
@@ -170,7 +170,7 @@ void DOS_BuildUMBChain(bool umb_active,b
bool DOS_LinkUMBsToMemChain(Bit16u linkstate);
/* FCB stuff */
-bool DOS_FCBOpen(Bit16u seg,Bit16u offset);
+Bit16u DOS_FCBOpen(Bit16u seg,Bit16u offset);
bool DOS_FCBCreate(Bit16u seg,Bit16u offset);
bool DOS_FCBClose(Bit16u seg,Bit16u offset);
bool DOS_FCBFindFirst(Bit16u seg,Bit16u offset);
diff -up ./src/dos/dos_classes.cpp.orig ./src/dos/dos_classes.cpp
diff -up ./src/dos/dos_files.cpp.orig ./src/dos/dos_files.cpp
--- ./src/dos/dos_files.cpp.orig 2015-12-27 10:08:26.000000000 -0800
+++ ./src/dos/dos_files.cpp 2015-12-27 12:22:17.000000000 -0800
@@ -964,7 +964,7 @@ bool DOS_FCBCreate(Bit16u seg,Bit16u off
return true;
}
-bool DOS_FCBOpen(Bit16u seg,Bit16u offset) {
+Bit16u DOS_FCBOpen(Bit16u seg,Bit16u offset) {
DOS_FCB fcb(seg,offset);
char shortname[DOS_FCBNAME];Bit16u handle;
fcb.GetName(shortname);
@@ -972,7 +972,7 @@ bool DOS_FCBOpen(Bit16u seg,Bit16u offse
/* First check if the name is correct */
Bit8u drive;
char fullname[DOS_PATHLENGTH];
- if (!DOS_MakeName(shortname,fullname,&drive)) return false;
+ if (!DOS_MakeName(shortname,fullname,&drive)) return (Bit16u)false;
/* Check, if file is already opened */
for (Bit8u i=0;i<DOS_FILES;i++) {
@@ -982,16 +982,16 @@ bool DOS_FCBOpen(Bit16u seg,Bit16u offse
if (handle==0xFF) {
// This shouldnt happen
LOG(LOG_FILES,LOG_ERROR)("DOS: File %s is opened but has no psp entry.",shortname);
- return false;
+ return (Bit16u)false;
}
fcb.FileOpen((Bit8u)handle);
- return true;
+ return handle;
}
}
if (!DOS_OpenFile(shortname,OPEN_READWRITE,&handle)) return false;
fcb.FileOpen((Bit8u)handle);
- return true;
+ return handle;
}
bool DOS_FCBClose(Bit16u seg,Bit16u offset) {
@@ -1181,11 +1181,12 @@ bool DOS_FCBGetFileSize(Bit16u seg,Bit16
char shortname[DOS_PATHLENGTH];Bit16u entry;Bit8u handle;Bit16u rec_size;
DOS_FCB fcb(seg,offset);
fcb.GetName(shortname);
- if (!DOS_OpenFile(shortname,OPEN_READ,&entry)) return false;
+ if (!(entry = DOS_FCBOpen(seg, offset))) return false;
handle = RealHandle(entry);
Bit32u size = 0;
Files[handle]->Seek(&size,DOS_SEEK_END);
- DOS_CloseFile(entry);fcb.GetSeqData(handle,rec_size);
+ fcb.GetSeqData(handle,rec_size);
+ DOS_CloseFile(entry);
Bit32u random=(size/rec_size);
if (size % rec_size) random++;
fcb.SetRandom(random);