assembly - 清屏不间断

标签 assembly x86 masm 32-bit irvine32

我正在使用 MASM 编写游戏,

我使用 ClrScr,它是 Irvine32.inc 中的一个过程

但它无法清理整个控制台窗口

一些字符仍然存在。

我的代码在32位系统下运行,所以我无法使用“int”指令

我正在尝试编写一个程序将黑色空间输出到整个控制台

但是当我调用该过程时它会闪烁。而且很难盯着屏幕..

有解决办法吗?


更新

这是我清除屏幕的代码

ForceCLS  PROC
    PUSH ECX
        Translate 0,0   ;Gotoxy 0, 0
        LoopTimes 50    ;Same AS MOV ECX, 50
        SettingColor Black ;Set Font Color to Black
        NewLine:
            PUSH ECX
                LoopTimes 115
                BLANKS:
                    Write 020H
                        ; Same As MOV EAX, 020H ; CALL  WriteChar
                    Loop BLANKS
            POP  ECX
            NL ;New Line
            Loop NewLine
    POP  ECX

    Translate 0,0   ;Same As Gotoxy 0, 0
    DefaultColor    ;Set Font Color to Default
    RET
ForceCLS ENDP

以下是输出示例:

enter image description here

最佳答案

之所以会出现闪烁,是因为当您清除控制台时,它会暂时变为空白。

为了防止这种闪烁,您需要在内存缓冲区中渲染场景,然后将缓冲区输出到控制台。您可以使用WriteConsoleOutput函数用于此。

这是 Windows 控制台中动画的简单示例。最有趣的部分发生在 ANIMATION 循环中。 RenderScene 过程将场景渲染到 buffer,而 WriteConsoleOutput 函数将此缓冲区的内容发送到控制台。

TITLE Animation example


INCLUDE Irvine32.inc
INCLUDE win32.inc


COLS = 80               ; number of columns
ROWS = 25               ; number of rows
CHAR_ATTRIBUTE = 0Fh    ; bright white foreground


.data
console HANDLE 0
buffer CHAR_INFO ROWS * COLS DUP(<<'-'>, CHAR_ATTRIBUTE>)
bufferSize COORD <COLS, ROWS>
bufferCoord COORD <0, 0>
region SMALL_RECT <0, 0, COLS-1, ROWS-1>

x DWORD 0               ; current position
y DWORD 2               ; of the figure
character WORD '0'      ; filled with this symbol


.code
main PROC
    INVOKE GetStdHandle, STD_OUTPUT_HANDLE
    mov console, eax    ; save console handle

    mov ecx, 70         ; draw 70 frames
ANIMATION:
    push ecx
    call RenderScene
    invoke WriteConsoleOutput, console, 
           ADDR buffer, bufferSize, bufferCoord, ADDR region
    INVOKE Sleep,250    ; delay between frames
    pop ecx
    loop ANIMATION

    exit
main ENDP


ClearBuffer PROC USES eax 
    xor eax, eax

BLANKS:  
    mov buffer[eax * CHAR_INFO].Char, ' '
    inc eax
    cmp eax, ROWS * COLS
    jl BLANKS

    ret       
ClearBuffer ENDP


CharToBuffer PROC USES eax edx bufx:DWORD, bufy:DWORD, char:WORD 
    mov eax, bufy
    mov edx, COLS
    mul edx
    add eax, bufx
    mov dx, char
    mov buffer[eax * CHAR_INFO].Char, dx
    ret
CharToBuffer ENDP


RenderScene PROC USES eax edx ecx
    CALL ClearBuffer

    ; render 10 by 7 rectangle
    mov edx, y
    mov ecx, 7
ONELINE:
    mov eax, x

    push ecx
    mov ecx, 10

ONECHAR:
    INVOKE CharToBuffer, eax, edx, character
    inc eax
    loop ONECHAR    ; inner loop prints characters

    inc edx
    pop ecx
    loop ONELINE    ; outer loop prints lines

    inc x           ; increment x for the next frame
    inc character   ; change fill character for the next frame

    ret
RenderScene ENDP


END main

此示例使用了一些未包含在 Irvine32.inc 中的函数和结构,因此我在 win32.inc 文件中添加了一些声明:

CHARTYPE UNION
    UnicodeChar    WORD ?
    AsciiChar      DB ?
CHARTYPE ENDS

CHAR_INFO STRUCT
    Char          CHARTYPE <>
    Attributes    WORD ?
CHAR_INFO ENDS

WriteConsoleOutput EQU <WriteConsoleOutputA>

WriteConsoleOutput PROTO,
    hConsoleOutput:HANDLE,
    lpBuffer:PTR CHAR_INFO,
    dwBufferSize:COORD,
    dwBufferCoord:COORD,
    lpWriteRegion:PTR SMALL_RECT

关于assembly - 清屏不间断,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34217344/

相关文章:

assembly - 是否可以在VM中使用VMX CPU指令?

assembly - SIMD指令用于浮点相等比较(NaN == NaN)

assembly - 在 x86 上执行 cli 后丢失中断会发生什么?

assembly - MASM 不会插入带有某些 CPU 和 FPU 指令组合的 x87 WAIT 前缀

push vs. mov(stack vs. near memory)的成本,以及函数调用的开销

windows - 一个简单的 MASM32 程序的奇怪行为

linux - 以前错误的未对齐调用现在可以工作了吗?

c - 函数调用是否与 %rax 以外的其他寄存器混淆?

c++ - 在 Assembly 中添加四个以上的参数

c++ - 如何使用汇编程序(x64 OS)获取进程环境 block (PEB)地址?