如何在汇编中打印ASCII数组?

时间:2019-06-01 12:02:21

标签: assembly graphics x86-16 dosbox

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

我附上了阵列和有问题的打印程序。如果有人发现问题,我将很高兴。

感谢您的帮助!

问题: 当我运行程序时,一切正常,直到“打印车”程序正常工作为止。它可以工作,但不是在屏幕上打印汽车,而是在同一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

1 个答案:

答案 0 :(得分:3)

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

inc cx

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

3 跳过黑色像素可能是一个好主意,也可能不是一个好主意。这取决于在绘制汽车之前是否清除了屏幕的那部分。

3 因为外部循环使用mov cx, [Xcar]而不是重新加载mov dx, 140,所以您会得到歪斜的图片!这是故意的吗?

4 在内循环中使用DX将不可避免地将所有像素置于相同的Y坐标上。该指令必须在开始外部循环之前执行,并且您需要在内循环完成时增加add cx, si寄存器。

5 因为BH指令位于代码的一部分内,每种黑色都会被跳过,因此X坐标不会像预期的那样前进。

6 BIOS.WritePixel函数需要 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 寄存器中的显示页面参数。使用显示页面0。这需要在代码中使用寄存器的方式上稍作改动。

完成的代码并进行了所有必要的更正:

<option value-"<?echo your id?>"><?php echo $row ["name"]; ?></option>