我正在尝试用汇编语言8086打印精灵。我已经编写了代码,但它没有显示任何内容。
.model small
.stack 100h
.data
sprite DB 00h,00h,00h,00h,00h,00h,00h,00h,0Fh,00h,00h,00h,00h,00h,00h ; 0
DB 0Fh,0Fh,0Fh,00h,00h,00h,00h,00h,0Fh,0Fh,0Fh,07h,00h,00h,00h ; 1
DB 00h,0Fh,0Fh,07h,07h,07h,00h,00h,00h,00h,0Fh,07h,07h,07h,07h ; 2
DB 00h,00h,00h,0Fh,0Fh,07h,07h,07h,07h,00h,00h,00h,0Fh,0Fh,07h ; 3
DB 07h,07h,07h,00h,00h,00h,0Fh,0Fh,07h,07h,07h,07h,00h,00h,00h ; 4
DB 0Fh,0Fh,07h,07h,08h,08h,00h,00h,00h,0Fh,0Fh,07h,07h,08h,08h ; 5
DB 00h,00h,00h,00h,0Fh,07h,07h,07h,07h,00h,00h,00h,00h,0Fh,07h ; 6
DB 07h,07h,07h,00h,00h,00h,07h,07h,0Fh,07h,07h,07h,00h,00h,07h ; 7
DB 07h,07h,07h,0Fh,0Fh,07h,00h,00h,07h,07h,00h,07h,07h,07h,0Fh ; 8
DB 00h,00h,07h,07h,00h,07h,07h,07h,07h,00h,00h,00h,00h,00h,07h ; 9
DB 07h,07h,07h,00h,00h,00h,00h,00h,07h,07h,07h,07h,00h,00h,00h ; 10
DB 00h,00h,00h,07h,07h,07h,00h,00h,00h,00h,00h,00h,07h,07h,00h ; 11
counter1 db ?
counter2 db ?
bullet_pos_x db 10
.code
main proc
mov ax, @data
mov ds, ax
mov si, 0
mov counter1, 0
mov counter2, 0
; Initialize CX and DX for sprite positioning
mov cx, 100 ; Set initial X position within the screen (between 0 and 319)
mov dx, 50 ; Set initial Y position within the screen (between 0 and 199)
drawOuter6:
drawInner6:
mov ah, 0ch ; Set AH to 0Ch for plot pixel function
mov al, sprite[si] ; Load pixel color into AL
int 10h ; Plot the pixel
inc cx ; Increment column counter
inc counter2 ; Increment inner loop counter
inc si ; Move to next pixel in sprite
cmp counter2, 9 ; Check inner loop counter
jl drawInner6 ; Repeat inner loop if less than 9 pixels
mov counter2, 0 ; Reset inner loop counter
mov cl, bullet_pos_x ; Load bullet_pos_x into the low byte of CX
inc dx ; Increment row counter
inc counter1 ; Increment outer loop counter
cmp counter1, 20 ; Check outer loop counter
jl drawOuter6 ; Repeat outer loop if less than 20 rows
end_print:
; Exit to DOS
mov ax, 4C00h
int 21h
main endp
end main
我已经写了代码,但它没有显示任何内容。
您看不到任何输出,因为您忘记设置图形模式。根据您提到的“(0和319之间)”和“(0和199之间)”,这必须是256色320x200图形模式13h。代码如下:
mov ax, 0013h ; AH=00h BIOS function number, AL=13h Mode number
int 10h
将初始化该特定视频模式。
mov cl, bullet_pos_x ; Load bullet_pos_x into the low byte of CX
您不想让您的精灵占据一个宽度为 9 像素、高度为 20 像素的常规矩形吗?在第一行使用
CX=100
,然后在其他行使用 CX=10
不会让事情保持在一起!可能 bullet_pos_x db 10
的本意是读作 bullet_pos_x db 100
。在下面的解决方案中,我实现了一个更简单的解决方案:由于内部循环已将 CX 提高了 9,因此只需从 CX 中减去 9 即可返回到精灵的左侧。
counter1 db ? counter2 db ? bullet_pos_x db 10
只要有可能,最好避免使用基于内存的变量。在您的程序中,您仍然有 3 个未使用的寄存器(BX、DI 和 BP)。在下面的代码中,我将内部计数器放置在 BP 中,将外部计数器放置在 DI 中。我还设置了 BH=0,因为通常 BIOS 期望 BH 包含显示页码。我相信 emu8086 不需要这个但是......
mov ax, @data
mov ds, ax
mov ax, 0013h ; AH=00h BIOS function number, AL=13h Mode number
int 10h
mov bh, 0 ; Select display page (some BIOSes require this)
mov cx, 100 ; Set initial X position
mov dx, 50 ; Set initial Y position
xor si, si ; Better than `mov si, 0` but same function
mov di, 20 ; Outer loop counter
drawOuter6:
mov bp, 9 ; Inner loop counter
drawInner6:
mov al, sprite[si] ; Load pixel color into AL
mov ah, 0Ch ; Set AH to 0Ch for plot pixel function
int 10h ; Plot the pixel
inc cx ; Increment X
inc si ; Move to next pixel in sprite
dec bp ; Check inner loop counter
jnz drawInner6 ; Repeat inner loop if less than 9 pixels
sub cx, 9
inc dx ; Increment Y
dec di ; Check outer loop counter
jnz drawOuter6 ; Repeat outer loop if less than 20 lines
给自己一个机会实际看到屏幕上显示的内容。您可以等待用户按下键盘上的任意键,然后再返回 DOS。大多数时候,将视频模式重置为标准 16 色 80x25 文本模式 03h 就是您想要的:
mov ah, 00h ; BIOS.WaitKeystroke
int 16h
mov ax, 0003h ; AH=00h BIOS function number, AL=03h Mode number
int 10h
mov ax, 4C00h ; DOS.Terminate
int 21h