如何在 Assembly 中打印 ASCII 数组?

How to print ASCII array in Assembly?

我正在尝试在 Assembly 的图形模式下制作汽车游戏。 为此,我必须在屏幕上打印一辆汽车,我可以用键盘在 x 轴上移动它。 我正在尝试打印一个 ASCII 数组,但它不起作用。

附上有问题的数组和打印程序。如果有人能发现问题,我会很高兴。

感谢您的帮助!

问题: 当我是 运行 程序时,一切正常直到 'printing car' 程序必须工作。它可以工作,但它不是在屏幕上打印汽车,而是在同一个 x 轴上打印许多分散的像素。

car db 0,0,0,0,0,0,0,0,0,0,0,4,4,4,4,4,4,4,4,4,0,0,0,0,0,0,0,0,0,0,0          
    db 0,0,0,0,0,0,0,0,4,4,4,4,4,0,0,0,0,0,4,4,4,4,4,0,0,0,0,0,0,0,0       
    db 0,0,0,0,0,4,4,4,4,4,4,4,4,0,4,0,4,0,4,4,4,4,4,4,4,4,0,0,0,0,0   
    db 0,0,0,0,4,4,4,4,4,4,4,4,0,4,4,4,4,4,0,4,4,4,4,4,4,4,4,0,0,0,0   
    db 0,0,0,4,4,14,14,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,14,14,4,4,0,0,0
    db 0,0,0,4,14,14,4,4,4,4,4,0,4,4,4,4,4,4,4,0,4,4,4,4,4,14,14,4,0,0,0 
    db 0,0,4,4,14,14,4,4,4,4,0,0,4,4,4,4,4,4,4,0,0,4,4,4,4,14,14,4,4,0,0 
    db 0,0,4,4,14,4,4,4,4,4,0,0,0,0,0,0,0,0,0,0,0,4,4,4,4,4,14,4,4,0,0
    db 0,0,4,4,4,4,4,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,4,0,4,4,4,4,4,0,0
    db 0,0,4,4,0,4,0,0,0,4,4,4,4,4,4,4,4,4,4,4,4,4,0,0,0,4,0,4,4,0,0
    db 0,0,0,4,0,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,0,4,0,0,0
    db 0,0,0,4,0,0,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,0,4,0,0,0
    db 0,0,0,4,0,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,0,4,0,0,0
    db 0,0,0,4,0,0,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,0,0,4,0,0,0
    db 0,4,4,4,4,0,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,0,4,4,4,4,0
    db 0,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,0,4,4,4,4,4
    db 0,0,0,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,0,0,0  
    db 0,0,0,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,0,0,0
    db 0,0,0,4,4,4,4,4,4,4,0,0,0,0,0,0,0,0,0,0,0,4,4,4,4,4,4,4,0,0,0 
    db 0,0,0,4,4,4,4,4,4,0,0,0,0,0,0,0,0,0,0,0,0,0,4,4,4,4,4,4,0,0,0
    db 0,0,0,4,4,4,4,4,4,0,0,0,0,0,0,0,0,0,0,0,0,0,4,4,4,4,4,4,0,0,0
    db 0,0,0,4,4,4,4,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,4,4,4,4,0,0,0
    db 0,0,0,4,4,4,4,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,4,4,4,4,0,0,0
    db 0,0,0,4,4,4,4,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,4,4,4,4,0,0,0
    db 0,0,0,4,4,4,4,4,4,0,0,0,0,0,0,0,0,0,0,0,0,0,4,4,4,4,4,4,0,0,0 
    db 0,0,4,4,0,4,4,4,4,0,0,0,0,0,0,0,0,0,0,0,0,0,4,4,4,4,0,4,4,0,0
    db 0,0,4,4,0,0,4,4,4,4,0,0,0,0,0,0,0,0,0,0,0,4,4,4,4,0,0,4,4,0,0
    db 0,0,4,4,0,0,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,0,0,4,4,0,0
    db 0,0,4,4,4,0,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,0,4,4,4,0,0
    db 0,0,4,4,4,4,0,0,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,0,0,4,4,4,4,0,0
    db 0,0,0,4,4,4,4,0,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,0,0,4,4,4,0,0,0
    db 0,0,0,4,4,4,4,0,0,4,4,4,4,4,4,4,4,4,4,4,4,4,0,0,4,4,4,4,0,0,0
    db 0,0,0,0,4,4,4,4,0,0,4,4,4,4,4,4,4,4,4,0,0,0,0,4,4,4,4,0,0,0,0
    db 0,0,0,0,4,4,4,4,4,4,0,0,0,0,0,0,0,0,0,0,0,4,4,4,4,4,4,0,0,0,0
    db 0,0,0,0,0,4,4,4,4,4,4,0,0,0,0,0,0,0,0,0,4,4,4,4,4,4,0,0,0,0,0

Xcar dw 150


proc carP
    push ax
    push bx
    push cx
    push dx
    push si
    push di
    xor si, si
    xor di, di
    mov bx, offset car
    mov cx, [Xcar]
    BLoop:
        cmp [byte ptr bx], 0
        je Pixel
        mov al, [byte ptr bx] 
        mov ah, 0ch
        mov dx, 140
        add cx, si
        int 10h
    Pixel:
        inc bx
        inc si
        cmp si, 34
        jne BLoop
        mov si, 0
        inc cx
        inc di
        cmp di, 34
        jne BLoop

    pop ax
    pop bx
    pop cx
    pop dx
    pop si
    pop di
    ret
endp carP
push ax
push bx
push cx
push dx
push si
push di
...
pop ax
pop bx
pop cx
pop dx
pop si
pop di

1 当您使用堆栈来保存寄存器时,您必须 pop 它们的顺序与您 push 编辑它们的顺序相反!

push ax
 push bx
  push cx
   push dx
    push si
     push di
     ...
     pop di
    pop si
   pop dx
  pop cx
 pop bx
pop ax

2 我已经为您的 car 数据计算了 35 行,每行 31 个字节。这使得总共 1085 个字节。但是,您的嵌套循环处理 34 x 34 字节。那是 1156 字节!

3 跳过黑色像素可能是也可能不是一个好主意。这取决于您是否在绘制 car.

之前清除了那部分屏幕

3 因为外层循环使用inc cx而不是用mov cx, [Xcar]重新加载,你会得到一个歪斜的图片!这是故意的吗?

4 在内部循环中有 mov dx, 140 将不可避免地将所有像素放在同一个 Y 坐标上。该指令必须在开始外循环之前执行,并且您需要在完成内循环时递增 DX 寄存器。

5 因为 add cx, si 指令在代码的一部分中,每个黑色都会被跳过,所以 X 坐标不会像它应该的那样前进。

6 BIOS.WritePixel函数需要在BH寄存器中显示页面参数。使用显示第 0 页。这需要稍微改变寄存器在代码中的使用方式。

经过所有必要更正的完整代码:

    push    ax
    push    bx
    push    cx
    push    dx
    push    si
    push    di
    push    bp

    xor     di, di            ; Vertical counter 0..34 (35)
    mov     dx, 140           ; Topside Y
    mov     si, offset car
    mov     bh, 0             ; Display page 0
    cld                       ; DF=0 so pointer will auto-increment (*)
OuterLoop:
    xor     bp, bp            ; Horizontal counter 0..30 (31)
    mov     cx, [Xcar]        ; Leftside X

InnerLoop:
    lodsb                     ; Fetch data byte plus increment pointer (*)
    cmp     al, 0
    je      SkipPixel
    mov     ah, 0Ch           ; BIOS.WritePixel
    int     10h
SkipPixel:
    inc     cx                ; Next X coordinate
    inc     bp
    cmp     bp, 31            ; 31 bytes per row in DB for the car
    jb      InnerLoop

    inc     dx                ; Next Y coordinate
    inc     di
    cmp     di, 35            ; 35 rows of DB for the car
    jb      OuterLoop

    pop     bp
    pop     di
    pop     si
    pop     dx
    pop     cx
    pop     bx
    pop     ax
    ret