首页 > 解决方案 > 在汇编 8086 中重复指令

问题描述

我创建了 3 个看起来不错的正方形。我只想一遍又一遍地重复这个动画,我知道这并不难,但我找不到怎么做。解释是罗马尼亚语,对不起。

基本上我只想清除屏幕并让它们一遍又一遍地出现。感谢所有的支持。

.stack 100
.data
y1 dw 70
x  dw 70
y2 dw 120

x2 dw 130
y3 dw 70
y4 dw 120

x3 dw 190
y5 dw 70
y6 dw 120

l db 50; lungime
k db 50;latime
kfinal db 51
n db 50

.code
mov ax,@data
mov ds,ax
mov ah,0h
mov al,13h; comutare in modul grafic 13h (320 x 200)
int 10h

desen:
mov dx,y1
mov cx,x
mov al,1; culoare
mov bl,l; lungime linie
mov ah,0ch; scriere pixel, cu culoare in al, cx=x, dx=y
mov bh,0
ciclu1: int 10h ; aprindere pixel de coordonate (cx,dx)
push dx
mov dx,y2
call delay
call delay
call delay
call delay
int 10h
pop dx
inc cx
dec bl
jnz ciclu1
mov bl,k; latime

ciclu2: int 10h ; aprinde pixel de coord (cx,dx)
push cx
mov cx,x
call delay
call delay
call delay
call delay
int 10h
pop cx
inc dx
dec bl
jnz ciclu2
int 10h
mov dx,y3
mov cx,x2
mov al,14; culoare
mov bl,l; lungime linie
mov ah,0ch; scriere pixel, cu culoare in al, cx=x, dx=y
mov bh,0

ciclu3: int 10h ; aprindere pixel de coordonate (cx,dx)
push dx
mov dx,y4
call delay
call delay
call delay
call delay
int 10h
pop dx
inc cx
dec bl
jnz ciclu3
mov bl,k; latime
ciclu4: int 10h ; aprinde pixel de coord (cx,dx)
push cx
mov cx,x2
call delay
call delay
call delay
call delay
int 10h
pop cx
inc dx
dec bl
jnz ciclu4
int 10h
mov dx,y5
mov cx,x3
mov al,4; culoare
mov bl,l; lungime linie
mov ah,0ch; scriere pixel, cu culoare in al, cx=x, dx=y
mov bh,0

ciclu5: int 10h ; aprindere pixel de coordonate (cx,dx)
push dx
mov dx,y6
call delay
call delay
call delay
call delay
int 10h
pop dx
inc cx
dec bl
jnz ciclu5
mov bl,kfinal; latime ultimul patratel

ciclu6: int 10h ; aprinde pixel de coord (cx,dx)
push cx
mov cx,x3
call delay
call delay
call delay
call delay
int 10h
pop cx
inc dx
dec bl
jnz ciclu6
ret

delay:
push cx
mov cx, 0ffffh
et1: dec cx
jnz et1
pop cx
ret


mov ah,4ch
int 21h
end


标签: assemblyx86-16

解决方案


一些重要的观察

  • 首先让我印象深刻的是,您没有为程序变量使用描述性名称,从而使事情变得复杂!请参阅下面的一些更好的名称。

    y1 dw 70
    x  dw 70
    y2 dw 120
    
    x2 dw 130
    y3 dw 70
    y4 dw 120
    
    x3 dw 190
    y5 dw 70
    y6 dw 120
    
    Box1Left    dw 70
    Box1Top     dw 70
    Box1Bottom  dw 120
    
    Box2Left    dw 130
    Box2Top     dw 70
    Box2Bottom  dw 120
    
    Box3Left    dw 190
    Box3Top     dw 70
    Box3Bottom  dw 120
    
  • 尽管您已将宽度和高度都设置为 50 ( l db 50 ;lungime k db 50 ;latime),但您绘制的框的表面为 51x51。

  • 在绘制最终的 LowerRightCorner 点时,您的第一个(蓝色)框和第二个(黄色)框使用与第三个(红色)框不同的系统。这是为什么?为什么要使用额外的变量kfinal db 51

  • 绘制框的代码以ret指令结尾,但它不是call-ed。这是错误的。此外,终止到 DOS 的代码是无法访问的,因为它位于另一ret条指令之下。

  • 与其将整个方框图代码重复 3 次,不如将它放在一个子例程中并让它call编辑 3 次。

        mov  al, 1        ; Blue
        mov  cx, Box1Left
        mov  dx, Box1Top
        mov  bp, Box1Bottom
        call DrawBox
        mov  al, 14       ; Yellow
        mov  cx, Box2Left
        mov  dx, Box2Top
        mov  bp, Box2Bottom
        call DrawBox
        mov  al, 4        ; Red
        mov  cx, Box2Left
        mov  dx, Box2Top
        mov  bp, Box2Bottom
        call DrawBox
    
        mov  ax, 4C00h    ; DOS.Terminate
        int  21h
    
    DrawBox:
        mov  ah, 0Ch      ; BIOS.WritePixel
        mov  bh, 0        ; DisplayPage
        push cx           ; (1)
    
        mov  bl, 50       ; Width = Length of the horizontal line
    ciclu1:
        int  10h
        xchg dx, bp
        int  10h
        xchg dx, bp
        inc  cx
        dec  bl
        jnz  ciclu1
    
        pop  bp           ; (1)
        mov  bl, 51       ; Height = Length of the vertical line
    ciclu2:
        int  10h
        xchg cx, bp
        int  10h
        xchg cx, bp
        inc  dx
        dec  bl
        jnz  ciclu2
        ret
    

你的问题的答案

基本上我只想清除屏幕并让它们一遍又一遍地出现。

如果这就是你想要的,那么你只需要重新启动你的程序。您的程序已经通过清除屏幕开始,因为它将视频模式设置为 13h。
请给用户一个机会来停止你的程序。在下面的示例代码中查看我是如何做到的:

    mov  ax, @data
    mov  ds, ax

Again:
    mov  ah, 00h
    mov  al, 13h; comutare in modul grafic 13h (320 x 200)
    int  10h

    ; Here you draw the boxes! Use the above code snippet...

    mov  ah, 00h      ; BIOS.WaitKey Wait for the user to press any key
    int  16h          ; -> AX
    cmp  al, 27       ; Did the user press <ESC> ?
    je   Exit         ; Yes
    jmp  Again        ; No, restart the program (this could be a big jump)

Exit:
    mov  ax, 4C00h    ; DOS.Terminate
    int  21h

; All subroutines go here, below the Exit to DOS!

您可以在这篇文章中阅读有关绘图的更多信息 How to create and draw sprites in emu8086?


推荐阅读