移动正方形时无法保持正方形完整



我一直在尝试在程序集中绘制一个框并将其水平移动 隔着屏幕。打印正方形本身的代码对我有用,但是当我尝试让它移动时,它的效果不是很好。我可以看到它在移动,但不是作为一个完整的正方形,如果你明白我的意思。

我的代码:在程序集 Tasm 中

STA SEGMENT STACK
DB 0FFFeH DUP(?)
STA ENDS
DATA SEGMENT
;-----------
;VARIABLES HERE
xpos dw 50h
ypos dw 50h
color db 9h
constat equ 0ffffh
siNum dw ?
diNum dw ?
numOFtime dw 0h
;-------------
DATA ENDS
CODE SEGMENT
ASSUME CS:CODE,DS:DATA,SS:STA
START :
MOV AX,DATA
MOV DS,AX
;start coding here:
mov ah, 0   ;Set display mode
mov al, 13h ;13h = 320x200, 256 colors
int  10H   ;Video BIOS Services
mov cx,50h
mov dx,50h
mov si,25H
mov di,25H
PrintSquare:
;------------------------------------------------------------------------
;cx = xpos , dx = ypos, si = x-length, di = y-length, al = color
didi:
mov color,9h
mov bp,0h
do:
add cx,si
here:
mov bh,0h
mov al,color
mov ah, 0Ch   ;write pixel at coordinate
int 10h      ;draw pixel!
dec cx
cmp cx,xpos
ja here
inc dx
inc bp
cmp bp,25h
jbe do
call drawBlackBox
inc numOFtime
inc xpos;incrising to make the sqaure moving horizontically
mov cx,xpos;cx gets the xposition
mov dx,ypos
cmp numOFtime,constat
jb didi



mov ah,004Ch  ;terminate program
int 21h
;
drawBlackBox proc
mov color,0h ;black color 
mov bp,0h
mov cx,xpos
mov dx,ypos
do1:
add cx,si
here1:
mov bh,0h
mov al,color
mov ah, 0Ch   ;write pixel at coordinate
int 10h      ;draw pixel!
dec cx
cmp cx,xpos
ja here1
inc dx
inc bp
cmp bp,25h
jbe do1
mov cx,xpos
ret
drawBlackBox endp

CODE ENDS
END START

如果移动不好,你的意思是边缘似乎在不同的时间移动,这是一个通常通过双重缓冲解决的问题(撕裂)。该问题是由于您正在渲染到活动(可见)图面,因此屏幕可能会显示半修改的帧。

插图可能会有所帮助。假设您正在尝试从左侧图像更改为右侧图像:

~   ~             ^   ^
O   O             O   O
^      ---->      ^
|---|             ___/

如果图像从左到右更新,并且数据在更新过程中发送到屏幕,您将看到类似以下内容:

^   ~
O   O
^
_--|

这就是所谓的撕裂。

要解决这个问题,您可以在单独的内存块中构建下一帧(您可以使用rep stosb在最短的时间内构建下一帧),然后使用rep movsb或类似的快速方式将其传输到视频内存。这会稍微降低您的帧速率,但应该可以减轻您可能看到的任何撕裂。


下面是一个实际演示示例。它的功能与您的功能类似,但使用双缓冲来解决撕裂问题,并且在执行特定操作的函数方面,它的结构也更好一些(在我看来无论如何):

stacksg segment stack
db 0fffeh dup(?)
stacksg ends
datasg segment
buffer dw 32000 dup(0)
datasg ends
codesg segment
assume cs:codesg, es: datasg, ds:datasg, ss:stacksg
doline: ; ax = line, bx = column, cx = width
push        di            ; preserve
push        ax
push        dx            ; imul hits this
push        bx            ; get byte offset to di
mov         bx, 320
imul        bx
pop         bx
add         ax, bx
mov         di, ax
push        cx            ; blat line
mov         al, 9    
cld
rep stosb
pop         cx
pop         dx            ; restore and return
pop         ax
pop         di
ret
dosquare: ; ax = line, bx = column, cx = width, dx = height
push        ax            ; preserve
push        bx
push        cx
push        dx
push        di            ; clear buffer to black
push        ax
push        cx
xor         di, di
xor         ax, ax
mov         cx, 32000
cld
rep stosw
pop         cx
pop         ax
pop         di
makeline:
call        doline
inc         ax
dec         dx
jnz         makeline
push        es            ; blat double buffer to screen
push        si
push        di
xor         si, si
mov         ax, 0a000h
mov         es, ax
xor         di, di
mov         cx, 32000
cld
rep movsw    
pop         di
pop         si
pop         es
pop         dx            ; restore and return
pop         cx
pop         bx
pop         ax
ret
start:
mov         ax, datasg
mov         ds, ax
mov         es, ax
mov         ah, 0         ; set display mode 13h, 320x200, 8bbp
mov         al, 13h
int         10h
mov         ax, 10        ; line
mov         bx, 10        ; start column
mov         cx, 40        ; width
mov         dx, 40        ; height
printSquare:
call        dosquare      ; do the square
inc         bx            ; move right but reset at end
cmp         bx, 310 - 40
jne         printSquare
mov         bx, 10
jmp         printSquare
codesg ends
end start

将其插入 GNU Turbo 汇编程序并检查出来。我运行了您的原始(撕裂)代码和此变体,后者的动画要流畅得多。

最新更新