【问题标题】:x86 Strange printing after console has been scrolled滚动控制台后x86奇怪的打印
【发布时间】:2016-06-01 21:29:37
【问题描述】:

我有以下功能:

printRows proc
    mov cx, 25
    printRowsLoop:  
        mov si, 0
        printSingleRowLoop:

            mov ah, 3  ;save current cursor position  at dx (dh:dl)
            int 10h

            push dx ;keep the position for later

            mov ah, 2
            mov dl, '&'   
            int 21h      ; print '&' char in the current curser position

            pop dx   ; restore dx

            add dl, 5 ; increase the column of it with a const number (so it would look like a square)
            mov ah, 2
            int 10h

            inc si
            cmp si, 3 ; print 3 '&' in each row
            jne printSingleRowLoop 

        mov dl, 13     ; result of these 3 groups of commands should be 2 new lines
        mov ah, 2
        int 21h

        mov dl, 10
        ;mov ah, 2 ; ah is alredy 2
        int 21h

        ;mov dl, 10 ; dl is already 10
        ;mov ah,2  ; ah is already 2
        int 21h

        loop printRowsLoop  ; print (cx) lines 
    ret

printRows endp

它的输出应该是在this screenshot 中看到的 - 这是它的输出(至少在开始时)

但是,在“好”输出填满控制台之后(当它需要“滚动”时)它不再打印每个 '&' 之间的那些空格,而是将它们中的每一个打印在一个新行中 @987654322 @。

什么可能导致这种奇怪的行为?我究竟做错了什么?我应该如何解决这个问题?

我正在使用emu8086。

【问题讨论】:

    标签: assembly x86 x86-16 emu8086


    【解决方案1】:

    您应该最后打印回车符(13 ascii 代码)。

    我的回答中也包含了Fifoernik 的提示。

    printRows proc
    mov cx, 25
    printRowsLoop:  
        mov si, 0
        printSingleRowLoop:
    
            push cx
            mov bh, 0
            mov ah, 3  ;save current cursor position  at dx (dh:dl)
            int 10h  
            pop cx
    
    
            push dx ;keep the position for later
    
            mov ah, 2
            mov dl, '&'   
            int 21h      ; print '&' char in the current curser position
    
            pop dx   ; restore dx
    
            mov bh, 0
            add dl, 5 ; increase the column of it with a const number (so it would look like a square)
            mov ah, 2
            int 10h
    
            inc si
            cmp si, 3 ; print 3 '&' in each row
            jne printSingleRowLoop 
    
    
            mov dl, 10
            ;mov ah, 2 ; ah is alredy 2
            int 21h
    
            ;mov dl, 10 ; dl is already 10
            ;mov ah,2  ; ah is already 2
            int 21h
    
            mov dl, 13    ; <<<<<<<<<<<<<<<<<<<<< print the carriage return last!
            ;mov ah, 2 ; ah is already 2 
            int 21h  
    
        loop printRowsLoop  ; print (cx) lines 
    ret
    
    printRows endp
    

    不需要额外的空格字符:)

    【讨论】:

    • 您的代码有一些错误!在 SetCursor 调用周围,您写了 push bxpop dx。这些都不是必需的,并且由于不匹配完全是错误的。请删除它们。
    • 如果您的解决方案解决了滚动问题,那么 emu8086 一定是一个非常非常非常糟糕的程序。
    • 我修正了这些错误,谢谢。我猜 emu8086 确实是一个糟糕的程序(它有很多错误)。你会如何解决这个问题?
    • 我没有解决这个滚动问题的办法。您找到的就是所谓的解决方法。对于任何需要使用 emu8086 的人来说,这可能是他们唯一的选择。我赞成你的回答。
    【解决方案2】:

    您的代码有一些问题:

    • BIOS 游标函数需要指定 BH 参数。它代表显示页面。最好设置为零。

    • BIOS GetCursor 调用将破坏循环控制所需的 CX 寄存器。您实际上并不需要 CX 中返回的值,因此只需 PUSH/POP 即可。

    使用这个:

    ...
    push cx
    mov bh, 0  ;display page 0
    mov ah, 3  ;save current cursor position  at dx (dh:dl)
    int 10h    ;GetCursor
    pop cx
    ...
    mov bh, 0  ;display page 0
    mov ah, 2
    int 10h    ;SetCursor
    ...
    

    通常这些修正并不能解决滚动问题,但emu8086是一个有很多问题的程序。你可能会走运!

    【讨论】:

    • 我知道我应该这样做(并且我在我的真实代码中这样做),我只是尝试发布一个最小、完整且可验证的示例。这些修复并不能解决我的问题。
    • @maniacsilversmith:如果您取出需要初始化的 args 的初始化,听起来您的代码太少了。为了清楚起见,可能希望将问题更新为避免这些问题的代码。
    【解决方案3】:

    问题在于您插入换行符的方式。你要做的是显示char 13、10、10。解决方法是在换行符后显示一个空格(13、10、10、''):

    mov dl, ' '
    mov ah, 2
    int 21h
    

    要对齐第一行,我们必须在开头显示另一个空格:

    printRows proc
        mov ah, 2    ;<=============================================
        mov dl, ' '  ;<=============================================
        int 21h      ;<=============================================
    
        mov cx, 25
        printRowsLoop:  
            mov si, 0
            printSingleRowLoop:
    
                mov ah, 3  ;save current cursor position  at dx (dh:dl)
                int 10h
    
                push dx ;keep the position for later
    
                mov ah, 2
                mov dl, '&'   
                int 21h      ; print '&' char in the current curser position
    
                pop dx   ; restore dx
    
                add dl, 5 ; increase the column of it with a const number (so it would look like a square)
                mov ah, 2
                int 10h
    
                inc si
                cmp si, 3 ; print 3 '&' in each row
                jne printSingleRowLoop 
    
            mov dl, 13     ; result of these 3 groups of commands should be 2 new lines
            mov ah, 2
            int 21h
    
            mov dl, 10
            ;mov ah, 2 ; ah is alredy 2
            int 21h
    
            ;mov dl, 10 ; dl is already 10
            ;mov ah,2  ; ah is already 2
            int 21h
    
            mov dl, ' ' ;<=============================================
            mov ah, 2   ;<=============================================
            int 21h     ;<=============================================
    
            loop printRowsLoop  ; print (cx) lines 
        ret
    
    printRows endp
    

    【讨论】:

    • 您的代码确实解决了一个问题,还是您的代码“解决”了emu8086中的一个错误(作为一种解决方法)?我真的不需要也不希望每行开头都有这样的空间。我不明白为什么我需要一个,我的原始代码对我来说似乎是正确的。你能解释一下吗?
    • @maniacsilversmith,是滚动混淆了光标位置。有时在显示某些内容之前无法正确识别换行符。当显示空白时,光标位置被强制更新,因此您的代码可以正确“保存”其新位置(在循环的开头)。显示空白对您的代码来说并没有什么大的变化,但它可以解决您的问题。
    • @maniacsilversmith,您的循环在底部显示换行符,但在开头“保存”光标位置,中间不显示任何内容。滚动后,需要显示一些东西。
    猜你喜欢
    • 2018-10-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-09-22
    • 2020-09-18
    • 2012-07-24
    • 2023-03-18
    相关资源
    最近更新 更多