程序集x86 - 第一次显示字符串不起作用

时间:2016-01-13 23:17:33

标签: assembly x86

我在Assembly 8086中构建了一个代码,它从用户那里得到一个字符串,然后将其打印出来。

这是我的代码:

        call displayNewLine         ;Displays a new line
        mov [byte ptr si + 14], '$' ;Set's the last char in the string to a $
        add si, 2                   ;Prevent from showing the first two chars (When receiving a string)
        mov dx, si                  ;SI contains the offset where the string starts
        mov ah, 09h         
        int 21h

当我运行它时,它只显示几个空格(从它看起来它只打印出字符串和$之间的字符。)

截图:

enter image description here

但是,由于某种原因,当我添加另一个int 21h时,它可以工作:

    call displayNewLine         ;Displays a new line
    mov [byte ptr si + 14], '$' ;Set's the last char in the string to a $
    add si, 2                   ;Prevent from showing the first two chars (When receiving a string)
    mov dx, si                  ;SI contains the offset where the string starts
    mov ah, 09h         
    int 21h
    int 21h

出于某种原因,此代码有效,而在第二个int 21h上,它会显示实际文本。

截图:

enter image description here

displayNewLine:

proc displayNewLine                             ;A function that displays a new line
    mov dl, 10
    mov ah, 2
    int 21h
    ret
endp displayNewLine

我试图将carrige移回右侧,但同样发生了。

是什么原因导致第一次不显示文字?

如果您需要更多详情或更好的解释,请发表评论!

1 个答案:

答案 0 :(得分:3)

这可以归结为这样一个事实,即您已经对'$'的放置位置进行了硬编码。

如果我们用空格或NUL字节之外的其他东西初始化缓冲区会更容易看到发生了什么,例如:

buf: db 10,0,'0123456789ABCDEF'

现在,int 21h / ah=0ah的说明指出,buf+2您最终会以“[实际字符读取],包括最终回车

因此,如果您输入“test”,之后您的缓冲区将如下所示:

10,0,'test\r56789ABCDEF'    ; \r == carriage return

然后你决定将'$'终结符放在buf+14,给你:

10,0,'test\r56789AB$DEF'

现在从buf+2开始打印,这与您打印test\r56789AB','$'时的打印方式相同。

“test”打印,但随后滑块返回结果,光标移回当前行的开头,并从那里打印其余字符(“56789AB” )。

当您第二次执行中断时,当前行上已经有“56789AB”,然后打印“test”导致“56789ABtest”,回车再次将光标移动到当前行的开头行,其余字符被打印出来(因此“56789AB”将打印在已经存在的“56789AB”上。

如果你用空格或NUL字节初始化缓冲区而不是“01234 ...”,那么当你使用一个中断时,看起来好像没有打印过,当你使用两个中断时,你会得到一些东西像:

C:\>program
test
       test

TL; DR:您的输入字符串将包含回车符,您应该将'$'放在回车符的位置而不是硬编码的位置[si+14]