3

我是组装新手,我遵循的课程使用EMU8086。我写了这段代码来打印Testing和 50 的 ASCII 代码,它是数字2,但它只打印Testing并忽略其余部分。怎么了?

.model tiny
.code

org 100h


main proc

    mov ah, 09h
    mov dx, offset msg
    int 21h 
    mov ah, 4ch
    mov dx ,0  
    mov dl, 2
    add dl, 48
    int 21h      

endp

msg db "Testing$"

end main

在阅读了@500 - Internal Server Error 的评论后,我将我的代码更新为:

.model tiny
.code

org 100h


main proc

    mov ah, 09h
    mov dx, offset msg
    int 21h 
    mov dl, 2
    add dl, 48
    int 21h      

endp

msg db "Testing$"

end main

它仍然无法正常工作,所以出了什么问题?

4

2 回答 2

1

DOS中断INT 21h/AH=9h不打印字符值,而是打印$终止字符串开头的内存偏移量。

DOS 1+ - 将字符串写入标准输出

AH = 09h

DS:DX -> '$' 终止的字符串

返回:

AL = 24h('$' 终止字符串,尽管官方文档声明没有返回任何内容)(至少 DOS 2.1-7.0 和 NWDOS)

如果要打印INT 21h/AH=9h的单个字符,则需要将值移动到以$符号终止的缓冲区中。然后将该缓冲区的地址传递给INT 21h/AH=9h。根据您的第二个示例,这样的事情应该可以工作:

.model tiny
.code
org 100h

main proc
    mov ah, 09h             ; DOS Interrupt ah=9h print $ terminated string
    mov dx, offset msg      ; Address of msg 
    int 21h                 ; Int 21h/ah=9h Print msg 
    mov outchar, 48+2       ; Move ASCII val for `2` to outchar buffer
    mov dx, offset outchar  ; Address of the $ terminated outchar buffer in DX
    int 21h                 ; AH is still 9h, so this prints $ terminated string

    mov ax, 4c00h           ; Exit program with return value 0
    int 21h    
endp

msg db "Testing$"           ; msg string
outchar db ?, "$"           ; output buffer for single character terminated with $

end main

而不是mov outchar, 48+2你可以像这样使用 ASCII 值:

mov outchar, '2'

或者,您可以通过将所需的字符放入输出缓冲区的中间来一次调用INT 21h/AH=9h :

main proc
    mov outchar, '2'    ; Place the ASCII value for '2' in the output buffer
    mov ah, 09h         
    mov dx, offset msg  
    int 21h             ; Print $ terminated string starting at `msg`
    mov ax, 4c00h
    int 21h             ; Exit with error code 0
endp

msg     db "Testing"
outchar db ?, "$"

这样做的原因是因为INT 21h/AH=9h会盲目地打印从偏移量开始找到的所有内容,msg直到找到$终止字符。我们outchar首先有效地进行了字符的替换,以便在执行INT 21h/AH=9h时它会Testing2$在内存中遇到。

一旦到达,$它将停止打印,因此输出如下所示:

测试2


您还可以选择使用两个不同的 DOS (INT 21h) 中断。INT 21h/AH=9h打印$终止的字符串,而INT 21h/AH=2h显示单个字符:

DOS 1+ - 将字符写入标准输出

AH = 02h

DL = 要写入的字符

返回:AL = 最后一个字符输出(尽管官方文档没有返回任何状态)(至少 DOS 2.1-7.0)

您可以对程序进行编码以msg像您一样显示字符串,但是您可以使用INT 21h/AH=2h来显示单个字符。您的代码可能如下所示:

.model tiny
.code
org 100h

main proc
    mov ah, 09h             ; DOS Interrupt ah=9h print $ terminated string
    mov dx, offset msg      ; Address of msg 
    int 21h                 ; Int 21h/ah=9h Print msg 
    mov ah, 02h             ; DOS interrupt ah=2h print single character
    mov dl, '2'             ; DL = ASCII value of character to print
    int 21h                 ; Int 21h/ah=2h print single character in DL 

    mov ax, 4c00h           ; Exit program with return value 0
    int 21h    
endp

msg db "Testing$"           ; msg string

end main
于 2016-06-06T13:54:28.190 回答
1

你的第二个代码几乎没问题,你只是忘记了服务号码ah来告诉int 21h你该怎么做:

.model tiny
.code

org 100h


main proc

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

    mov ah, 2          ;<==== AH=2 : INT 21H WILL DISPLAY CHARACTER IN DL.
    mov dl, 2
    add dl, 48
    int 21h      

endp

msg db "Testing$"

end main
于 2016-06-06T16:13:52.523 回答