为什么会出现与 DOS PSP 的未格式化参数区不一致的情况?

Mis*_*o50 3 assembly dos

对于 MS-DOS 和 IBM-DOS(我正在使用后者),从地址 80h 开始,内存中有一个保留部分用于传递命令行参数。地址 80h 是一个计数器,用于计算该长度,地址 81h 是 ASCII 参数开始的位置。问题是这个内存区域似乎很少真正按预期工作。

当我加载debug.com参数时LOADME,内存看起来有点像这样。

-D 80 8F
1039:0080  00 0D 4C 4F 41 44 4D 45-0D 00 00 00 00 00 00 00  ..LOADME........
Run Code Online (Sandbox Code Playgroud)

这里的不一致之处在于地址 80H,它应该包含一个计数器,但显然只读出了 0,尽管LOADME它完整存在。如果我向程序中输入更大的参数,事情只会变得更加不一致。为了进行比较,参数如下所示LOADME NOW

-D 80 8F
1039:0080  04 20 4E 4F 57 0D 4D 45-20 4E 4F 57 0D 00 00 00  . NOW.ME NOW....
Run Code Online (Sandbox Code Playgroud)

现在计数器读数为 4,这更接近正确的值,但仍然不正确。此外,LOAD已从参数列表中完全删除。我还拼凑了两个程序,一个来自 StackOverflow,另一个是我自己设计的。StackOverflow 程序运行完美,能够输出正确的输入。

MOV AH, 40
MOV BX, 0001
XOR CH, CH
MOV CL, [0080]
MOV DX, 0081
INT 21 ; Write directly to device 1, with memory address 80h as your counter and your string beginning at 81
MOV AX, 4C00
INT 21 ; Exit
Run Code Online (Sandbox Code Playgroud)

无论您向该程序输入什么内容,它都能够将准确的数据输出到屏幕上。不幸的是,除了制作 echo 命令的副本之外,这在用途上非常有限。

反过来,我创建了这个程序,它让我复制 81H 处的内存部分并尝试读取它。该程序无法按预期工作,并且在运行时大多会输出乱码数据。这可能是由于编程错误造成的,因为这是我第一次在程序中进行无指导的尝试,但它有助于理解我的观点。

XOR AX, AX ; Clearing out the registers.
XOR BX, BX
XOR CX, CX
XOR DX, DX
MOV DX, 0300 ; A variable offset that I left unused
MOV AX, [0080] ; The counter
MOV BX, 0080 ; The current read position
ADD BX, 01; Begin loop
MOV CX, [BX]
ADD BX, 0300 ; Jump to our offset
MOV [BX], CX
SUB BX, 0300 ; Remove our offset in memory. 
DEC AX
JNZ 0111
ADD BX, 0301 ; Loop ended here.
MOV CX, 0024 ; Now, at the end of the string, add a $.
MOV [BX], CX
MOV AH, 09
MOV BX, 301
INT 21 ; Execute "display string"
MOV AX, 4C
INT 21 ; End program
Run Code Online (Sandbox Code Playgroud)

它肯定会读取参数所在的位置,但忽略它倾向于覆盖参数所在位置的事实,它似乎并没有一致地这样做,只闪烁我期望输出的片段,然后再擦除它们。

这真的是 IBM-DOS 的问题吗,还是在debug.com捉弄我,而我是一个糟糕的程序员?

Nas*_*sau 5

嗯,实际上这是正确的,因为

\n

80h - 命令行上的字节数

\n

81h\xe2\x80\x93FFh - 命令行尾部(以 0Dh 终止)

\n

在第一个示例中,0Dh 偏移量为 81h,因此 80h = 0

\n

在第二个示例中,0Dh 偏移量为 85h,因此 80h = 4

\n

LOADME 不是在当前目录中找到的程序名称。

\n

调试程序名参数

\n
\n

更新1:

\n

Debug LOADME

\n

偏移量 81h 如下所示:

\n

(20h space)LOADME(0dh)

\n

然后系统检查 LOADME 是否是正确的文件路径。不是那么检查params是否存在吗?不,没有什么了,所以 0dh 在 81h 被打印。

\n

(0dh)LOADME(0dh)

\n
\n

Debug LOADME NOW

\n

偏移量 81h 如下所示:

\n

(20h space)LOADME(20h space)NOW(0dh)

\n

LOADME 不是正确的文件路径,因此在 81h = 0dh 处打印此内容,现在缓冲区如下所示:

\n

(0dh)LOADME(20h space)NOW(0dh)

\n

并检查下一个输入,即(20h 空间)NOW(0dh)。所以覆盖,从81h开始。

\n

(20h space)NOW(0dh)ME(20h space)NOW(0dh)

\n
\n

更新2:

\n

我不知道还要添加什么。我可以写东西,但这是否是您正在寻找的答案?

\n

DOS可以加载和执行两种类型的文件:com和exe。执行的程序及其环境称为进程。\nDOS 一次只能运行一个进程。内存中的常驻程序除外。进程可以调用另一个\n进程来暂时挂起其工作。然后程序创建父子进程的层次结构。在大多数情况下,父级将是command.com。PSP 中的偏移量 16h 显示父进程段,因此如果我运行 debug.exe,父进程段为 0b18 (command.com)

\n

C:>debug.exe\n-d 0\n1181:0000  CD 20 FF 9F 00 9A EE FE-1D F0 4F 03 E5 0B 8A 03\n1181:0010  E5 0B 17 03 E5 0B 18 0B-01 01 01 00 02 FF FF FF\n1181:0020  FF FF FF FF FF FF FF FF-FF FF FF FF 20 09 4E 01\n...\n1181:0080  00 0D 63 6F 6D 6D 61 6E-64 2E 63 6F 6D 0D 65 79\n
Run Code Online (Sandbox Code Playgroud)

\n

如果我检查段 0b18,这确实是 command.com 的 PSP。父进程段是0b18,这意味着command.com没有父进程。指向自身。

\n

0B18:0000  CD 20 FF 9F 00 9A F0 FE-1D F0 7E 01 18 0B 4A 01\n0B18:0010  18 0B 55 01 18 0B 18 0B-01 01 01 00 02 FF FF FF\n0B18:0020  FF FF FF FF FF FF FF FF-FF FF FF FF C3 0B F2 05\n...\n1181:0080  00 0D 63 6F 6D 6D 61 6E-64 2E 63 6F 6D 0D 65 79\n
Run Code Online (Sandbox Code Playgroud)\n还有一个叫做DTA(磁盘传输区)的东西

\n

Source Wikipedia

\n

DTA 的初始地址被设置为覆盖 PSP 中存储命令行参数的区域(地址为 0x80),这样程序需要在调用使用 DTA 的 DOS 函数之前解析该区域以获取命令行参数。 DTA(例如读入文件记录),除非程序注意将 DTA 的地址更改为其他内存区域(或者完全不使用 DTA/FCB 函数,该函数很快就被弃用,转而使用文件句柄)。

\n

您可以使用 更改此设置ah=1ah int 21h并请求 DTA 地址ah=2fh int 21h。只是我发现的,从未测试过这个功能。

\n
\n

更新3:

\n

如果我运行debug testcode.exe -a abc -3内存转储,看起来像这样:

\n

0BA0:0000  CD 20 FF 9F 00 9A F0 FE-1D F0 4F 03 9A 05 8A 03\n0BA0:0010  9A 05 17 03 9A 05 89 05-01 01 01 00 02 FF FF FF\n0BA0:0020  FF FF FF FF FF FF FF FF-FF FF FF FF 47 0B 4C 01\n.....\n0BA0:0080  0A 20 2D 61 20 61 62 63-20 2D 33 0D 78 65 20 2D  . -a abc -3.xe -\n
Run Code Online (Sandbox Code Playgroud)

\n

这是testcode.exe,在偏移81h处我们可以看到确切的参数列表。\n父进程位于这里05 89,它是debug.exe在偏移81h处是debug的参数。

\n

0589:0000  CD 20 FF 9F 00 9A F0 FE-1D F0 DE 01 1E 04 4B 01\n0589:0010  1E 04 56 01 1E 04 1E 04-01 01 01 00 02 FF FF FF\n0589:0020  FF FF FF FF FF FF FF FF-FF FF FF FF 2F 05 B9 49
\n.....\n0589:0080 17 20 74 65 73 74 63 6F-64 65 2E 65 78 65 20 2D . testcode.exe -\n0589:0090 61 20 61 62 63 20 2D 33-0D 20 54 33 0D 74 2E 65 a abc -3. T3.t.e\n
Run Code Online (Sandbox Code Playgroud)

\n

debug的父进程位于这里04 1E,它是cmd.exe,因为我这次在windows下运行了它。

\n

041E:0000  CD 20 FF 9F 00 9A F0 FE-1D F0 7F 01 1E 04 4B 01\n041E:0010  1E 04 56 01 1E 04 1E 04-01 01 01 00 02 FF FF FF\n041E:0020  FF FF FF FF FF FF FF FF-FF FF FF FF C9 04 FA 05\n.....\n041E:0080  17 20 74 65 73 74 63 6F-64 65 2E 65 78 65 20 2D  . testcode.exe -\n041E:0090  61 20 61 62 63 20 2D 33-0D 20 54 33 0D 74 2E 65  a abc -3. T3.t.e\n
Run Code Online (Sandbox Code Playgroud)

\n

  • @Missingno50 debug.com 有自己的 PSP,您正在查看加载程序中的 PSP (3认同)