过度使用大宏是否会导致我的图像绘制程序出现问题?

问题描述 投票:0回答:2

我对这段代码有疑问。将图片打印到屏幕时,它会挂起,就像进入无限循环一样。它可以工作,但停止绘图。
另外,当你跳过不断挂起的部分时,会直接报错。
我在互联网上搜索但找不到任何结果。我正在等待您的帮助。

.model small  
.stack 64
.DATA 
.CODE
screen macro  
    mov ah,00
    mov al,13h
    int 10h
endm
clear_screen macro  
    mov ax,600h 
    mov bh,07h 
    mov cx,0    
    mov bx,184fh 
    int 10h
endm
yatay macro x,y,c
    local myloop 
    local loop2
    mov cx,x  
    mov dx,y  
    mov bh,0h
    mov bl,5 
    loop2:
    mov [200h],bl
    mov [202h],cx
    mov bl,5
    myloop:
        mov ah,0ch
        mov al,c 
        int 10h
        inc cx
        dec bl
        cmp bl,0
        jnz myloop 
    inc dx
    mov bl,[200h]
    mov cx,[202h]
    dec bl
    cmp bl,0
    jnz loop2
endm
main proc far
    mov ax,@data
    mov ds,ax   
    clear_screen
    screen 
    yatay 90d,1d,04  
    yatay 95d,1d,04 
    yatay 100d,1d,04 
    yatay 105d,1d,04 
    yatay 85d,5d,04
    yatay 105d,5d,04 
    yatay 110d,5d,04 
    yatay 75d,10d,04 
    yatay 80d,10d,04 
    yatay 90d,10d,04 
    yatay 95d,10d,04 
    yatay 100d,10d,04 
    yatay 110d,10d,04  
    mov ah,4ch  
    int 21h
main endp
end main
assembly graphics infinite-loop x86-16 emu8086
2个回答
1
投票

指令

 loop2: mov [200h],bl
bl
复制到
DS:200h
处的内存,但您没有在数据段中保留那么多空间,因此您覆盖了其他段中的某些内容,可能会发生奇怪的事情。

图形视频模式 13h (320*200) 使用从地址 A0000h 开始的内存,请参阅这个答案。如果您想通过直接写入视频内存进行绘制,请使用

初始化额外的段寄存器
MOV AX,0xA000
MOV ES,AX

例如,用它来每个像素写入一个字节

MOV [ES:DI],AL ; Draw color AL to DI-th pixel.

还要检查您的

clear_screen macro
,它错误地设置了寄存器
bx
的内容并覆盖了
bh
。当videomode设置为Int 10h/AH=00h时,屏幕已经是干净的,所以不需要
clear_screen


0
投票

还有,当你跳过不断挂起的部分时,直接报错

如果你知道程序是哪些部分挂起的,为什么不告诉我们?


您的程序挂起的原因是您正在覆盖程序的指令,正如 vitsoft 的答案中已经解释的那样。
如果您减少对宏的依赖,这种覆盖就不会发生!

您的 yatay 宏扩展到大约 50 个字节,并且您调用该宏 12 次。这意味着您的程序会因为数百个字节而变得臃肿!绘制实心矩形的代码需要成为您的程序可以使用的子例程,也许是为了在小宏中方便起见。

call

在您的绘图代码中,基本上您使用 200h 和 202h 处的内存来临时保存 
yatay macro x,y,c mov cx, x mov dx, y mov al, c call DrawRectangle endm

BL
的寄存器内容。
执行此操作的首选工具是堆栈
。只需用 CX
push bx
push cx
pop cx
围绕内循环即可。
pop bx

这段代码只是需要一些优化。

您不需要那些
    ; IN (al,cx,dx) DrawRectangle: mov bh, 0 mov bl, 5 loop2: push bx push cx mov bl, 5 myloop: mov ah, 0Ch int 10h inc cx dec bl cmp bl, 0 jnz myloop pop cx pop bx inc dx dec bl cmp bl, 0 jnz loop2 ret main proc far ...
  • 指令,因为
    cmp bl, 0
    指令本身已经定义了您想要在分支中使用的必要标志。
    您不需要保留/恢复 
  • dec bl
  • 寄存器。您
    知道
    内部循环已将其递增 5 倍,因此恢复只需减去 5 即可。 您不必为内部和外部循环使用相同的计数器寄存器,从而需要保留/恢复。您可以使用额外的寄存器,例如
  • CX
  • (或
    SI
    DI
    )。
    您可以使用一条指令加载字大小寄存器的两个字节大小的部分
  • BP
  • 。您只需添加描述性评论...
    
    
  • BX
提示:让你的筹码堆更大一点!说
; IN (al,cx,dx) DrawRectangle: mov bx, 0005h ; DisplayPage BH=0, OuterCount BL=5 OuterLoop: mov si, 5 InnerLoop: mov ah, 0Ch ; BIOS.PutPixel int 10h inc cx ; Next X dec si ; InnerCounter jnz InnerLoop sub cx, 5 ; Restore X inc dx ; Next Y dec bl ; OuterCounter jnz OuterLoop ret main proc far ...

    

© www.soinside.com 2019 - 2024. All rights reserved.