我正在浏览 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 向量指向的位置,您将看到 here它获取 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 的唯一方法是,如果你有一长串比较和条件跳转来测试所有可能的系统调用号并相应地分支到它们的入口点,这将比查找效率低得多表。
关于assembly - 我们如何仅通过使用它的名称而不使用与之关联的十六进制数来访问 DOS 函数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63542837/