TASM 精灵看起来很奇怪

TASM sprite looks weird

我最近开始使用 TASM 编写代码,目前正在研究精灵。在我的程序中,我收到一个精灵并将其打印在屏幕上(图形模式)。

该程序基本上运行良好,但打印的数字看起来很奇怪。本应位于彼此正下方的像素看起来有些距离。

我是这样调用函数的:

push 10 ; amount of lines
push 10 ; length of each line
push 4 ; color
push 100 ; y
push 160 ; x
push offset card2
call Sprite_Figure

函数如下:

proc Sprite_Figure
push bp
mov bp, sp
push ax
push bx
push cx
push dx
push si
    
    mov si, [bp+4] ; sprite offset
    mov cx, [bp+14] ; number of lines   
    loop1:
        mov dx, [bp+12] ; size of one line
        loop2:
            push dx
            xor dx, dx
            cmp [byte ptr si], 0
            je continue
            
            print:
            mov bx, [bp+8] ; current row    
            
            mov ax, 320
            mul bx
            mov bx, ax ; calculation to get location of pixel on screen
            add bx, [bp+6] ; x
            
            mov ax, [bp+10] ; color
            mov [es:bx], al ; color location, es val is 0A000h
            
            continue:
            pop dx
            inc si ; next element in array  
            dec dx
            inc [bp+6] ; right by one
            
            cmp dx, 0
            jne loop2
        
        mov ax, 320
        sub ax, [bp+12] ; the size of one line
        add [bp+6], ax ; new line
        inc [bp+8] ; one line down  
        dec cx
        cmp cx, 0
        jne loop1
pop si
pop dx
pop cx
pop bx
pop ax
pop bp
ret 12
endp Sprite_Figure  

精灵在屏幕上的样子:

有没有人有什么想法?

代码混合了 2 种向下移动的方式!这解释了为什么代码在屏幕上以双倍速率下降,值 320 被添加两次。

基本上你有几种绘制字符矩阵的方法:

  • 一对嵌套循环,您可以在其中改变 XY 坐标并每次计算屏幕上的地址。
  • 一对嵌套循环,您计算一次屏幕左上角像素的地址,然后根据需要更改该地址。

inc [bp+8]      ; one line down

适合第一种方法,而行

mov ax, 320
sub ax, [bp+12] ; the size of one line
add [bp+6], ax  ; new line

适合第二种方法

方法一

因为内层循环重复递增了X坐标,为了恢复,必须减去总递增次数:

    ...
    dec dx
    jnz loop2
    mov ax, [bp+12] ; Size of one line (number of increments)
    sub [bp+6], ax  ; X is now restored
    inc [bp+8]      ; Y+ one line down  
    dec cx
    jnz loop1

方法2

坐标仅用于获取BX地址一次。之后只有地址有所不同。循环中的指令少了很多,这意味着这是一种更有效的方法。

    mov ax, 320
    mul [word ptr bp+8] ; Y
    mov bx, ax
    add bx, [bp+6]      ; X

    mov si, [bp+4]      ; sprite offset
    mov cx, [bp+14]     ; number of lines   
    mov al, [bp+10]     ; color

loop1:
    mov dx, [bp+12]     ; size of one line

loop2:
    cmp [byte ptr si], 0
    je continue
    mov [es:bx], al     ; ES val is 0A000h
continue:
    inc si              ; next byte in character pattern
    inc bx              ; X+ right by one on screen
    dec dx
    jnz loop2

    sub bx, [bp+12]     ; Address of left side
    add bx, 320         ; Address of new line
    dec cx
    jnz loop1