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

kuhbmx9i  于 2023-05-29  发布在  其他
关注(0)|答案(1)|浏览(109)

对于MS-DOS和IBM-DOS(我使用的是后者),从地址80 h开始,内存中有一个保留部分用于沿着命令行参数。地址80 h是一个计数器,用于计算该长度,地址81 h是ASCII中参数的开始位置。问题是,这一记忆区域似乎很少真正像预期的那样工作。
当我用参数LOADME加载到debug.com中时,内存看起来有点像这样。

-D 80 8F
1039:0080  00 0D 4C 4F 41 44 4D 45-0D 00 00 00 00 00 00 00  ..LOADME........

这里的不一致是地址80 H,它应该包含一个计数器,但显然只读出一个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....

现在计数器读数为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

不管你给这个程序输入什么,它都能把准确的数据输出到屏幕上。不幸的是,除了复制echo命令之外,这种方法的使用非常有限。
反过来,我创建了这个程序,它可以让我复制81 H的内存部分,并尝试读取它。这个程序不能按预期的方式工作,而且在你运行它的时候,它大多数时候都是乱码。这可能是由于编程错误,因为这是我第一次在程序中进行无指导的尝试,但它有助于让我的观点得到理解。

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

它肯定会读取参数所在的位置,但忽略它倾向于覆盖参数所在的位置的事实,它似乎并不总是这样做,在擦除它们之前只 Flink 我期望输出的片段。
这真的是IBM-DOS的问题,还是debug.com在捉弄我,我是一个糟糕的程序员?

2w2cym1i

2w2cym1i1#

实际上这是正确的因为
80 h-命令行上的字节数
81 h-FFh-命令行尾部(以0 Dh结尾)
在第一示例中,0 Dh偏移是81 h,因此80 h = 0
在第二示例中,0 Dh偏移是85 h,因此80 h = 4
LOADME不是在当前目录中找到的程序名。
调试程序名参数
更新1:
Debug LOADME
偏移81 h看起来像:
(20h space)LOADME(0dh)
然后系统检查LOADME是否是文件的正确路径。它不是这样检查是否存在参数?不,没有更多的,所以0 dh在81 h打印。
(0dh)LOADME(0dh)
Debug LOADME NOW
偏移81 h看起来像:
(20h space)LOADME(20h space)NOW(0dh)
LOADME不是文件的正确路径,因此在81 h = 0 dh处打印此内容,现在缓冲区看起来像:
(0dh)LOADME(20h space)NOW(0dh)
并检查下一个输入,即(20 h空间)NOW(0 dh)。因此,覆盖,从81 h开始。
(20h space)NOW(0dh)ME(20h space)NOW(0dh)
更新2:
我不知道该加什么。我可以写东西,但如果这将是你的答案你在寻找?
DOS可以加载和执行两种类型的文件,com和exe。被执行的程序及其环境被称为进程。DOS一次只能运行一个进程。除了内存中的常驻程序。进程可以调用另一个进程暂时挂起它的工作。然后程序创建父子进程的层次结构。在大多数情况下,父节点是command.com。PSP中的偏移量16 h显示父进程的段,因此如果我运行debug.exe,则父进程段为0 b18(command.com)
``

C:>debug.exe
-d 0
1181:0000  CD 20 FF 9F 00 9A EE FE-1D F0 4F 03 E5 0B 8A 03
1181:0010  E5 0B 17 03 E5 0B 18 0B-01 01 01 00 02 FF FF FF
1181:0020  FF FF FF FF FF FF FF FF-FF FF FF FF 20 09 4E 01
...
1181:0080  00 0D 63 6F 6D 6D 61 6E-64 2E 63 6F 6D 0D 65 79

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

0B18:0000  CD 20 FF 9F 00 9A F0 FE-1D F0 7E 01 18 0B 4A 01
0B18:0010  18 0B 55 01 18 0B 18 0B-01 01 01 00 02 FF FF FF
0B18:0020  FF FF FF FF FF FF FF FF-FF FF FF FF C3 0B F2 05
...
1181:0080  00 0D 63 6F 6D 6D 61 6E-64 2E 63 6F 6D 0D 65 79

还有一种叫做DTA(磁盘传输区)的东西
Source Wikipedia
DTA的初始地址被设置为覆盖PSP中的区域(在地址0x 80),其中存储命令行参数,使得程序需要在调用利用DTA的DOS函数之前解析该区域以获得命令行参数(例如阅读文件记录),除非程序小心地将DTA的地址更改为其他内存区域(或者不完全使用DTA/FCB函数,这些函数很快就被弃用,转而支持文件句柄)。
您可以使用ah=1ah int 21h更改此设置,并请求DTA地址ah=2fh int 21h。只是我发现,从来没有测试过这个功能。
更新3:
如果我运行debug testcode.exe -a abc -3内存转储看起来像这样:
``

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

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

0589:0000  CD 20 FF 9F 00 9A F0 FE-1D F0 DE 01 1E 04 4B 01
0589:0010  1E 04 56 01 1E 04 1E 04-01 01 01 00 02 FF FF FF
0589:0020  FF FF FF FF FF FF FF FF-FF FF FF FF 2F 05 B9 49

.....
0589:0080  17 20 74 65 73 74 63 6F-64 65 2E 65 78 65 20 2D  . testcode.exe -
0589:0090  61 20 61 62 63 20 2D 33-0D 20 54 33 0D 74 2E 65  a abc -3. T3.t.e

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

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

相关问题