【问题标题】:How to pass/retrieve DOS command-line parameters in a 16-bit assembly program?如何在 16 位汇编程序中传递/检索 DOS 命令行参数?
【发布时间】:2017-05-17 20:33:47
【问题描述】:

我正在为 MS-DOS 编写一些小工具。现在我正在写一个Shutdown.com,就像Windows XP 和更高版本一样。我已经写了整个代码,现在我只需要从 DOS 传递参数。

我需要传递参数“-r”来重启,“-s”来关闭。

我该怎么做?

我在 Windows 98 上使用 TASM(Turbo Assembler 4.1) 进行链接和编译。我正在寻找一种非常简单的方法来做到这一点,如果可能的话,仍然是一个.COM 程序。我看起来与 C 语言中的 ARGV 和 ARGC 完全一样,但对于 16 位汇编...

  • shutdown -r 将重启
  • shutdown -s 将关闭

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

【问题讨论】:

  • 你打电话给什么实体?另一个程序? BIOS?汇编程序如何期望参数被传递?
  • .com 文件接收PSP at offset 80h 中的参数。该页面甚至有汇编示例代码;)
  • 作为一个兴趣点,您的 shutdown.com 是否有效?我以为 XP 及更高版本不允许 16 位应用程序关闭机器。
  • 他们当然不会,@klitos。他没有使用 Windows,他实际上是在编写一个 DOS 应用程序。你知道,它是在 DOS 下运行的,而不是 NT DOS。
  • @KlitosKyriacou Here 我关机时的代码。适用于 MS-DOS,但不适用于 Windows 98。在这里完美运行。

标签: assembly dos tasm 16-bit x86-16


【解决方案1】:

在 MS-DOS 中没有特定的 API 来检索命令行。相反,您必须从Program Segment Prefix (PSP) 的适当偏移量中读取值,这是 DOS 用来存储程序特定数据的数据结构。

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

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

Randall Hyde 的 Art of Assembly 的旧 16 位 DOS 版本可在线免费获得(HTMLPDF 格式)。在Chapter 13 中,第 13.3.11 节介绍了 PSP,以下两节 (13.3.12–13) 说明了如何访问和解析命令行参数,包括示例代码。

【讨论】:

  • 值得一提的是,第一个字节(在 81h 处)显然是空格或 '/',而不是您在 C main() 或 POSIX argv 中的 argv[1][0] 中所期望的。
【解决方案2】:

根据this site,命令行的长度存储在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 - 您可以先扫描“-”,在循环中或使用 repne scasb(cx = 计数,di = 地址),然后检查下一个字符是否为“r”或'R' or 's' or 'S' (你可以or 020h 并检查 'r' 或 's')。
  • 我该怎么做?我在这里尝试了一个小实验,但 id 不起作用。
  • .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”时打印,但不会起作用。
猜你喜欢
  • 2017-05-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-07-28
  • 1970-01-01
  • 2017-04-03
相关资源
最近更新 更多