我正在浏览MS-DOS 1.25源代码MSDOS.ASM,在这里我发现了由这些名称引入的MS-DOS内置函数,如下所示。正如我们所看到的系统标准功能的实现;RENAME";,这个函数是系统调用23,但值23没有被使用。
; Standard Functions
DISPATCH DW ABORT ;0
DW CONIN
DW CONOUT
DW READER
DW PUNCH
DW LIST ;5
DW RAWIO
DW RAWINP
DW RENAME
RENAME: ;System call 23
CALL MOVNAME
JC ERRET
ADD SI,5
MOV DI,OFFSET DOSGROUP:NAME2
CALL LODNAME
JC ERRET
CALL FINDNAME
JC ERRET
OR BH,BH ;Check if I/O device name
JS ERRET ;If so, can't rename it
MOV SI,OFFSET DOSGROUP:NAME1
MOV DI,OFFSET DOSGROUP:NAME3
MOV CX,6
REP MOVSW
我的困惑是系统如何识别RENAME函数,因为同一个函数在不同的模块中可能有不同的名称,并且没有附加十进制或十六进制值。正如我们所看到的,RENAME功能是系统调用23,但代码中没有使用这个值。仅使用RENAME变量名,我们无法访问它的代码。当我看到只有名字用冒号(:(符号的地方时,我很惊讶。就像我发现只有
CONIN:
在某些地方被使用。在这种情况下,期望的代码将如何执行,因为通过只写";CONIN";。我们无法访问欲望代码。
如果您更仔细地查看DISPATCH
表,您会发现dw RENAME
实际上是它的第23个元素(从零开始计数(。
如果你看一下COMMAND
,它是INT 21h向量指向的地方,你会看到它取AH中的值,并将其用作DISPATCH
数组的索引,然后调用这个地址:
MOV BL,AH
MOV BH,0
SHL BX,1
;; skip a couple lines
CALL CS:[BX+DISPATCH]
因此,RENAME
是系统调用23,即通过调用AH=23的INT 21h来访问,这一事实被编码在DISPATCH
表的布局中。符号RENAME
仅在DOS源代码中使用,用户程序不可用。事实上,如果你没有源代码,你就永远不会知道这个标签的名字。
查找表是操作系统调度系统调用的典型方式。否则,您实际需要使用系统调用编号23的唯一方法是,如果您有一长串比较和条件跳转来测试所有可能的系统调用编号,并相应地分支到它们的入口点,这将比查找表效率低得多。