额外细分未能在程序集

时间:2017-07-05 21:17:08

标签: assembly x86-16 tasm

我编写的游戏类似于汇编中的突破(工具:DosBOX,notepad ++,tasm),在图形模式下创建边框和平台时,我偶然发现了两个问题:

  1. 看起来似乎额外的片段没有注册颜色信息,因为我无法正确使用它,当我尝试拉它时,给我一个0是黑色的,而不是白色的是0Fh。
  2. 这是我试图解决的一个小问题,但由于某种原因,当我尝试绘制第二个和第三个边框时,第一个边框的一部分变成黑色,你会看到它,如果你运行代码。我无法确定它为什么会发生,而且调试器没有显示任何奇怪的内容。
  3. 这是我目前的代码,平台创建边框,平台和移动所涉及的主要步骤是BorderPaintPlatBuildPlatMove

        IDEAL
        MODEL small
        STACK 100h
        DATASEG
        platLoc dw 63806
        speed1 dw 10
        speed2 dw 0FFFFh
        CODESEG
        ;procedure to paint borders-6 px white pixels
        proc BorderPaint
            push ax
            push bx
            push di
            push cx
    
        mov ax,0A000h ;accesses graphics mode video memory
        mov es,ax
        xor di,di
    
        ;first line-left vertical
        ;sets color white
    
        mov ax,0Fh
        mov cx,200 ;enters nested loop
        FirstLoop1:
        push cx
        mov cx,6
        SecondLoop1:
        mov [es:di],ax
        inc di
        loop SecondLoop1
        sub di,6
        add di,320
        pop cx
        loop FirstLoop1
        ;second line- up horizontal
        mov di,7
        mov cx,313
        FirstLoop2:
        push cx
        mov cx,6
        SecondLoop2:
        mov [es:di],ax
        add di,320
        loop SecondLoop2
        sub di,1920
        inc di
        pop cx
        loop FirstLoop2
    
        mov di,314
        mov cx,200
        FirstLoop3:
        push cx
        mov cx,6
        SecondLoop3:
        mov [es:di],ax
        inc di
        loop SecondLoop3
        sub di,6
        add di,320
        pop cx
        loop FirstLoop3
    
        ; xor di,di
        ; mov ax,0Fh
        ; mov cx,200
        ; FirstLoop4:
        ; push cx
        ; mov cx,6
        ; SecondLoop4:
        ; mov [es:di],ax
        ; inc di
        ; loop SecondLoop4
        ; sub di,6
        ; add di,320
        ; pop cx
        ; loop FirstLoop4
    
            pop cx
            pop di
            pop bx
            pop ax
        ret
        endp BorderPaint 
    
        proc PlatBuild
        push di
        push cx
        push ax
            mov di,[platLoc]
            mov ax,5
            mov cx,40
            LoopPaint2:
            push cx
            mov cx,10
            LoopPaint1:
            mov [es:di],ax
            sub di,320
            loop LoopPaint1
            add di,320*10
            inc di
            pop cx
            loop LoopPaint2
        pop ax
        pop cx
        pop di
        ret
        endp PlatBuild
    
        Proc PlatErase
        push di 
        push cx 
        push ax
            mov di,[platLoc]
            mov ax,0
            mov cx,40
            LoopPaint4:
            push cx
            mov cx,10
            LoopPaint3:
            mov [es:di],ax
            sub di,320
            loop LoopPaint3
            add di,320*10
            inc di
            pop cx
            loop LoopPaint4
        pop ax
        pop cx
        pop di
        ret
        endp PlatErase
    
        Proc PlatMove
        push ax
        push cx
        push dx
        push di
            mov ax,0A000h
            mov es,ax
            call BorderPaint
            ;Input
            CheckPress1:
            mov ah,0h
            int 16h
    
    
            cmp al,'a'
            jne nxt11
            jmp MoveLeft1
             Nxt11:
            cmp al,'d'
            jne nxt12
            jmp MoveRight1
            Nxt12:
            cmp al,'q'
            jne CheckPress1
            jmp endproc1
    
            MoveLeft1:
            call Delay
            mov dx,[platLoc]
            add dx,8*320
            sub dx,1d
            mov di,dx
            mov ax,[es:di]
            cmp ax,0Fh
            jne move1
            jmp CheckPress1
            move1:
            call PlatErase
            dec [platLoc]
            call PlatBuild
            mov ah,1h
            int 16h
            je MoveLeft1
            jmp CheckPress1
    
            MoveRight1:
            call Delay
            mov dx,[platLoc]
            add dx,41
    
            mov di,dx
            mov ax,[es:di]
            cmp ax,0Fh
            jne move2
            jmp CheckPress1
            move2:
            call PlatErase
            inc [platLoc]
            call PlatBuild
            mov ah,1h
            int 16h
            je MoveRight1
            jmp CheckPress1
            EndProc1:
        pop di
        pop dx
        pop cx
        pop ax
            ret
            endp PlatMove
            proc Delay
        push cx
            mov cx, [speed2]    
        LoopLong:                                    
        push cx                  
            mov cx, [speed1]        
          LoopShort:                               
            loop LoopShort    
        pop cx                    
            loop LoopLong
        pop cx
        ret
        Endp Delay
        start:
            mov ax,@data
            mov ds,ax
            mov ax,13h
            int 10h
            call BorderPaint
            call PlatBuild
            mov ax, [es:63680]
            call PlatMove
    
        exit:
            mov ax,4c00h
            int 21h
        END startenter code here
    

2 个答案:

答案 0 :(得分:1)

  1. mov [es:di],ax将WORD(两个字节)写入VRAM ax = 0x000F,因此您以[es:di]0x0F[es:di+1]值{{1}写入(黑色)。
  2. 0x00

    这是亵渎:/ ... sub di,6 add di,320 仍然是源级别上可见的意图,但也显示出对机器的无知,减少了使用的指令量。

    顺便说一句,如果你想存储6个0x0F值的字节,你还可以存储三个字的0x0F0F值,​​节省一半的VRAM访问(这是很昂贵的)。那么

    add di,320-6

    是更优化的硬编码方式,如何绘制6个像素(只有3个VRAM写入)并在下面移动1行。

    1. 不确定,你的意思,但可能有一个问题可能是在 mov di,<some VRAM address> mov cx,<number of lines> mov ax,0F0Fh ; <color><color> (two pixels at same time) Draw6PixelsLoop: mov [es:di],ax mov [es:di+2],ax mov [es:di+4],ax add di,320 dec cx jnz Draw6PixelsLoop 中从VRAM读取单词(两个像素),然后将它们与0Fh PlatMove进行比较,即两个像素“白色+黑色” = cmp ax,0Fh。因此,在左侧,这可能会很好,但在右侧,它将只在边框的末端找到这样的两个像素(请记住,在右侧的最后一个像素之后,下一个字节是第一个左侧像素下一行,所以如果你有6像素强的边框,第一个白色+黑色像素位于左边框结束的下一行)。

答案 1 :(得分:1)

读写问题

由于您的程序使用320x200 256色视频模式13h,因此每个像素都由VRAM中的单个字节表示。代码中最重要的问题,也就是Ped7g已经指出这一点,就是你一直在读写单词,你应该在那里阅读和写字节
我将通过编写上边界的修正来表明我们的意思。 不要忘记在其他地方进行类似的更改!

;second line- up horizontal
    mov di,6          ; (6,0)   <--- See 1.
    mov cx,320-6-6    ; Width   <--- See 2.
FirstLoop2:
    push cx
    mov cx,6          ; Height
  SecondLoop2:
    mov [es:di],al    ; Color 0Fh, Byte from AL instead of word from AX
    add di,320        ; Go down 1 line
    loop SecondLoop2
    sub di,320*6      ; Take back 6 additions of 320
    inc di            ; Go right 1 pixel
    pop cx
    loop FirstLoop2

我选择此部分是因为它还有一些其他错误:

  1. 鉴于左侧边界宽度为6像素,顶部边框从像素位置6开始(xy位置从零开始)。
  2. 鉴于稍后您还将绘制一个6像素宽的右侧边框,您只需要绘制介于两者之间的内容:320-6-6
  3. 上面的代码可以进行很多优化,但目前你正努力让事情发挥作用。因此,请不要尝试一次处理超过1个像素。编程的一个重要座右铭是:“首先让它发挥作用,然后让它变得更好”。

    也写下我写的评论。它有助于理解你在做什么。

    测试颜色的问题

    MoveLeft1:
        call Delay
        mov dx,[platLoc]
        add dx,8*320         ???
        sub dx,1d
        mov di,dx
        mov ax,[es:di]       ???
        cmp ax,0Fh           ???
    

    MoveLeft1 代码中,您从错误计算的地址中读取!通过在dx注册表中添加8 * 320,您可以在屏幕下方 ,所以屏幕外。实际上由于分段环绕,你将错误地处理VRAM顶部的一些随机像素。

      MoveLeft1:
          call Delay
          mov  di, [platLoc]
          mov  al, [es:di-1]    ; Pixel to the left of the platform
          cmp  al, 0Fh          ; Is it white?
          jne  move1
          jmp  CheckPress1
        move1:
          call PlatErase
          dec  [platLoc]
          call PlatBuild
          mov  ah, 01h
          int  16h              ; Key pending?
          je   MoveLeft1
          jmp  CheckPress1
    
    MoveRight1:
        call Delay
        mov dx,[platLoc]
        add dx,41          ???
        mov di,dx
        mov ax,[es:di]     ???
        cmp ax,0Fh         ???
    

    MoveRight1 代码中,您还会从错误的地址读取。平台宽度为40像素,因此最后一个像素位于 platLoc + 39,因此需要检查的像素位于 platLoc + 40。

    MoveRight1:
        call Delay
        mov  di, [platLoc]
        mov  al, [es:di+40]     ; Pixel to the right of the platform
        cmp  al, 0Fh            ; Is it white?
        jne  move2
        jmp  CheckPress1
      move2:
        call PlatErase
        inc  [platLoc]
        call PlatBuild
        mov  ah, 01h
        int  16h                ; Key pending?
        je   MoveRight1
        jmp  CheckPress1