【问题标题】:DOS Assembler: MOV ah, 09h AND int 21h combination doesn't print anythingDOS 汇编程序:MOV ah, 09h AND int 21h 组合不打印任何内容
【发布时间】:2014-12-08 11:52:46
【问题描述】:

我正在编写一个关于 TASM 汇编语言的 DOS 命令行参数解析器。这是我的代码:

.model tiny
.386
.code
org 100h
start:


    mov ax, ax  
    mov bp, 80h
    mov si, 81h
    mov ch, 0
    mov cl, ds:[bp]
    push 0
    cmp cx, 0
    je FINISH

    CYCLE_BEGIN:
        lodsb
        cmp al, 2Fh
        je SLASH
        cmp al, 31h
        je ONE
        cmp al, 32h
        je TWO
        cmp al, 33h
        je THREE
        cmp al, 68h
        je HELP
        cmp al, 20h
        je SPACE
        mov bx, 6
        jmp CHANGE_STATE

        SLASH:
            mov bx, 0
            jmp CHANGE_STATE
        ONE:
            mov bx, 1
            jmp CHANGE_STATE
        TWO:
            mov bx, 2
            jmp CHANGE_STATE
        THREE:
            mov bx, 3
            jmp CHANGE_STATE
        HELP:
            mov bx, 4
            jmp CHANGE_STATE
        SPACE:
            mov bx, 5
        CHANGE_STATE:
            mov ax, 7
            mul dx
            add ax, bx
            mov dh, 0
            push si
            mov si, offset AU
            add si, ax
            lodsb
            mov dl, al
            pop si

        cmp dx, 6
        JE ERROR

        cmp dx, 1
        je HAVEONE
        cmp dx, 2
        je HAVETWO
        cmp dx, 3
        je HAVETHREE
        cmp dx, 4
        je HAVEHELP
        jmp CYCLE_END

        HAVEONE:
            mov ax, 0001h
            jmp SETFLAGS
        HAVETWO:
            mov ax, 0010h
            jmp SETFLAGS
        HAVETHREE:
            mov ax, 0100h
            jmp SETFLAGS
        HAVEHELP:
            mov ax, 1000h
        SETFLAGS:
            pop bx
            or bx, ax
            push bx
        CYCLE_END:
            dec cx
            jne CYCLE_BEGIN
    jmp SUCCESS
    ERROR:
        pop bx
        mov dx, offset merror
        mov ah, 09h
        int 21h
        jmp FINISH
    SUCCESS:
    pop bx
    mov dx, bx
    and dx, 1000h
    je MESSAGES_CHECK
    mov dx, offset mhelp
    mov ah, 09h
    int 21h
    jmp FINISH

    MESSAGES_CHECK:
    mov dx, bx
    and dx, 0001h
    je CHECK2
    mov dx, offset m1
    mov ah, 09h
    int 21h
    mov ah, 02h
    mov dl, 0dh
    int 21h
    mov dl, 0ah
    int 21h

    CHECK2:
    mov dx, bx
    and dx, 0010h
    je CHECK3
    mov dx, offset m2
    mov ah, 09h
    int 21h
    mov ah, 02h
    mov dl, 0dh
    int 21h
    mov dl, 0ah
    int 21h
    CHECK3:
    mov dx, bx
    and dx, 0100h
    je FINISH
    mov dx, offset m3
    mov ah, 09h
    int 21h

    FINISH:
        RET

        m1  db  'You have used /1 key$'
        m2  db  'You have used /2 key$'
        m3  db  'You have used /3 key$'
        mhelp   db  'ad.asm [/1 | /2 | /3| /h]$'
        merror  db  'Wrong input$'

        AU:;        / 1 2 3 h   *
        db  5,6,6,6,6,0,6 ;
        db  6,6,6,6,6,0,6 ; /1
        db  6,6,6,6,6,0,6 ; /2
        db  6,6,6,6,6,0,6 ; /3
        db  6,6,6,6,6,0,6 ; /h
        db  6,1,2,3,4,6,6 ; /
        db  6,6,6,6,6,6,6 ; err



end start

如果有/1,它应该打印m1的内容,如果有/2,它应该打印m2的内容,如果/3,它应该打印m3的内容。问题出在以下代码部分:

mov dx, offset m1
    mov ah, 09h
    int 21h
----

mov dx, offset m2
    mov ah, 09h
    int 21h
----

mov dx, offset m3
    mov ah, 09h
    int 21h

它不打印任何东西。即使我在 Turbo Debugger 中看到代码已到达并且dx 中有正确的偏移量,int 21h 之后的标准输出中也没有文本。为什么?

【问题讨论】:

  • 我只能使用dosbox进行检查,它在那里工作正常。
  • @Jester 你是如何编译代码的?
  • tasm test.asmtlink /t test.obj

标签: assembly x86 dos tasm


【解决方案1】:

CHANGE_STATE 的乘法没有意义,因为 DX 没有事先初始化!

CHANGE_STATE:
        mov ax, 7
        mul dx

希望这会有所帮助。

还因为您使用的是字符串原语lodsb,您可以确保清除方向标志cld

【讨论】:

  • 你是绝对正确的。问题在真正的 Win95 机器上是可重现的(除了“错误输入”之外的所有消息都被吞下);在源代码开头添加xor dx,dx 时问题消失。顺便说一句,在 Turbo Debug(例如td test.com /1)中没有出现问题,因为那里的所有寄存器(包括dx)都被初始化为零。也许OP 认为问题仍然存在,因为退出TD时所有输出都被清除了。如果您在调试时按 Alt-F5 检查控制台输出,那么您会看到消息正常。
【解决方案2】:

一个 DOS .com 应用程序仅将其所有代码和数据存储在一个段中,并且 DS 和 ES 已经初始化并在它开始执行时等于 CS。

...

为了获取一些命令行参数,建议获取之前PSP的段地址,因为当前PSP不一定是调用者的PSP,如果我们从父应用程序中使用exec函数启动子应用程序例如 AX=4B00h 的 int 21h。

RBIL->inter61b.zip->INTERRUP.H

--------D-2162-------------------------------
INT 21 - DOS 3.0+ - GET CURRENT PSP ADDRESS
AH = 62h
Return: BX = segment of PSP for current process
Notes:  this function does not use any of the DOS-internal stacks and may
thus be called at any time, even during another INT 21h call
the current PSP is not necessarily the caller's PSP
identical to the undocumented AH=51h
SeeAlso: AH=50h,AH=51h

【讨论】:

  • 这个答案没有任何意义。您需要使用程序自己的 PSP 来访问程序自己的命令行参数。在.COM 可执行文件中,DS、ES、CS 都被初始化为指向 PSP 段。这就是 ORG 100h 语句跳过位于段开头的 PSP 的原因。
猜你喜欢
  • 1970-01-01
  • 2016-08-15
  • 2020-01-28
  • 2021-07-19
  • 1970-01-01
  • 2011-12-13
  • 1970-01-01
  • 1970-01-01
  • 2022-11-18
相关资源
最近更新 更多