问题
I have been trying to draw a box in assembly and move it horizontally across the screen. The code of printing the square itself works for me but when I try to make it move it is not working very well. I can see it moving but not as a full square, if you get my point.
My code: in Assembly 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
回答1:
If, by not moving well, you mean the edges seem to move at different times, that's an issue (tearing) usually solved by double buffering. The problem is caused by the fact that you're rendering to an active (visible) surface so the screen may show half-modified frames.
An illustration may help. Let's say you're trying to change from the left image to the right:
~ ~ ^ ^
O O O O
^ ----> ^
|---| \___/
If the image is updated left to right and the data is sent to the screen halfway through your update process, you will see something like:
^ ~
O O
^
\_--|
This is what's known as tearing.
To solve it, you can construct the next frame in a separate memory block (you can use rep stosb
to construct the next frame in minimal time) then use rep movsb
, or something similarly speedy, to transfer that to video memory. That will slow down your frame rate a little but should alleviate any tearing you may be seeing.
Here's an example showing this in action. It's similar functionality to yours but uses double buffering to get around the tearing issue, and it's also a little better structured (in my opinion anyway) in terms of functions doing specific things:
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
Plug that into GNU Turbo Assembler and check it out. I ran both your original (tearing) code and this variant and the latter was much smoother animation.
来源:https://stackoverflow.com/questions/55579935/unable-to-keep-a-square-a-full-square-while-moving-it