如何在16位汇编程序中传递/检索DOS命令行参数?

7

我正在编写一些MS-DOS小工具。现在我正在编写一个Shutdown.com,类似于Windows XP及以上版本中的关机功能。我已经编写了整个代码,现在我只需要从DOS传递参数。

我需要传递参数“-r”来重新启动计算机,传递参数“-s”来关闭计算机。

我正在使用TASM(Turbo Assembler 4.1)在Windows 98上进行链接和编译。我正在寻找一种非常简单的方法来实现这一点,并且如果可能,仍然是一个.COM程序。我正在寻找与C语言的ARGV和ARGC完全相同的东西,但是针对16位汇编语言...

  • shutdown -r将重新启动计算机
  • shutdown -s将关闭计算机

请记住,我已经知道如何重新启动计算机和关闭计算机。
我只需要学习如何从MS-DOS命令行将参数传递给我的程序。


shutdown.com是一个命令行程序吗?也就是说,你可以在命令行中输入shutdown -r来使用它吗? - wallyk
2
.com文件在PSP偏移80h处接收参数。该页面甚至提供了汇编示例代码;) - Jester
1
作为一个有趣的点,你的shutdown.com工作吗?我认为XP及以上版本不允许16位应用程序关闭计算机。 - Klitos Kyriacou
1
当然不会,@klitos。他没有使用Windows,实际上他正在编写一个DOS应用程序。你知道的,那种在DOS中运行而不是NT DOS的应用程序。 - Cody Gray
1
@KlitosKyriacou 这里是我的关机代码。适用于MS-DOS,但在Windows 98上不起作用。这里运行得完美。 - MendaxRox
显示剩余4条评论
2个回答

10

没有特定的API可以检索MS-DOS中的命令行。相反,您必须从适当偏移处读取程序段前缀(PSP)的值,这是DOS用于存储程序特定数据的数据结构。

在偏移量80h处,有一个1字节的值,它给出了命令行参数的长度。实际的命令行参数字符串从81h偏移量开始,并且可以长达127个字节。你可以根据偏移量80h处的值知道它的长度,但它也将以回车符(0Dh)终止。

当程序首次执行时,您可以相对于DS寄存器中的指针使用这些偏移量。否则,您可以调用带有AH设置为62hINT 21h,以在BX寄存器中检索当前PSP的指针。(函数62h需要DOS 3或更高版本; 在DOS 2上,您可以使用未记录的函数51h)。

Randall Hyde的旧版16位DOS Art of Assembly可以在线免费获取(以HTMLPDF格式提供)。在第13章的第13.3.11节中描述了PSP,以下两个部分(13.3.12-13)解释了如何访问和解析命令行参数,包括示例代码。


值得一提的是,第一个字节(在81h处)显然将是空格或“/”,而不是您在C main()或POSIX argv中期望的argv [1] [0] - Peter Cordes

7
根据此网站,命令行的长度存储在DS:80h (单个字节)中,实际的命令行从DS:81h开始。以下是该文章中打印命令行的示例代码:
; ----------------------------------------------------------------------------
; echo.asm
;
; Echoes the command line to standard output.  Illustrates DOS system calls
; 40h = write to file, and 4ch = exit process.
;
; Processor: 386 or later
; Assembler: MASM
; OS: DOS 2.0 or later only
; Assemble and link with "ml echo.asm"
; ----------------------------------------------------------------------------

        .model  small
        .stack  64                      ; 64 byte stack
        .386
        .code
start:  movzx   cx,byte ptr ds:[80h]    ; size of parameter string
        mov     ah, 40h                 ; write
        mov     bx, 1                   ; ... to standard output
        mov     dx, 81h                 ; ... the parameter string
        int     21h                     ; ... by calling DOS
        mov     ah, 4ch
        int     21h
        end     start             

当我尝试比较dx上的ASCII字符时,我遇到了麻烦。我该如何比较这些字符? - MendaxRox
@MendaxRox - 你可以先扫描“-”,可以使用循环或者使用repne scasb(cx = 计数,di = 地址),然后检查下一个字符是否为“r”或“R”或“s”或“S”(你可以or 020h并检查“r”或“s”)。 - rcgldr
我该怎么做?我在这里尝试了一个小实验,但它没有起作用。 - MendaxRox
.model small .stack 64
.386 .code start: movzx cx,byte ptr ds:[80h]
mov ah, 40h
mov bx, 1
mov dx, 81h
cmp dl,'A' jnz sair int 21h
sair:
mov ah, 4ch int 21h end start此代码只在输入为'A'时输出,但无法工作。
- MendaxRox

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接