繁体   English   中英

多余的段不会在程序集中注册颜色数据

[英]Extra segment won't register color data in assembly

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

  1. 似乎多余的段不会记录颜色信息,因为我无法正确获取颜色信息,当我尝试拉动它时,它会给我一个0(黑色),而不是白色(0Fh)。
  2. 我试图解决这个小问题,但是由于某些原因,当我尝试绘制第二个和第三个边框时,第一个边框的一部分变成黑色,如果运行代码,就会看到它。 我无法确定为什么会发生这种情况,并且调试器没有显示任何异常情况。

这是我当前的代码,创建边框,平台和平台移动涉及的主要过程是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
  1. mov [es:di],ax将WORD(两个字节)写入VRAM, ax = 0x000F ,因此您以[es:di]0x0F[es:di+1]0x00 (黑色)进行写入。

    sub di,6
    add di,320

这是亵渎神灵:// ... add di,320-6在源代码级别仍保持可见的意图,但对机器的了解也较少,从而减少了使用的指令数量。

顺便说一句,如果要存储6个字节的0x0F值,则还可以存储3个字的0x0F0F值,​​从而节省了一半的VRAM访问(这很昂贵)。 所以呢

    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

是一种最佳的硬编码方式,即如何绘制6个像素(仅写入3个VRAM)并在其下方移动1行。


  1. 不确定,您的意思是什么,但可能的一个问题可能是从PlatMove VRAM中读取单词(两个像素),然后将它们与0Fh cmp ax,0Fh进行比较,即两个像素“ white + black” = 000Fh 因此,在左侧可能会很好地工作,但是在右侧,它只会在边框的末尾找到两个像素(请记住,在右侧的最后一个像素之后,下一个字节是像素上的第一个左侧像素下一行,因此,如果您有6个像素的边框,则第一个白色+黑色像素位于左边框结束的下一行。

读写问题

由于您的程序可在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

上面的代码可以进行很多优化,但是目前您正在努力使工作正常。 因此,请勿尝试一次处理超过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代码中,您从错误计算的地址中读取了! 通过将8 * 320添加到dx寄存器,您将降落在屏幕下方 ,从而离开屏幕。 实际上,由于段环绕,您将错误地寻址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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM