【问题标题】:FCB and Int 21h/function 23hFCB 和 Int 21h/功能 23h
【发布时间】:2016-03-29 21:24:47
【问题描述】:

我需要使用 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

我想怎么用这个?

【问题讨论】:

  • 请编辑问题并添加您正在考虑的硬件和操作系统。
  • 问得太晚了 32 年,FCB 在 1983 年就过时了。
  • 首先用所有必需的信息初始化一个FCB(我相信在文档的其他部分也有这方面的例子),然后调用 int 21h。

标签: assembly dos x86-16 tasm 16-bit


【解决方案1】:

您链接到的同一页面底部有一个指向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);

【讨论】:

    猜你喜欢
    • 2014-04-20
    • 2015-07-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-01-28
    • 1970-01-01
    相关资源
    最近更新 更多