assembly 如何设置边界移动的东西在屏幕上当用户按下键,在汇编?

xsuvu9jc  于 11个月前  发布在  其他
关注(0)|答案(1)|浏览(100)

假设我有一段代码,用wasd键使一个点在ES(额外的段)中移动,我如何检查这个点是否在第一行,如果是,它就不移动?
(我问老师是否需要使用cmp,他说不需要)
在向上运动的过程中;(我把BX设置为0来检查SI是否也是0,然后我只是做了一个循环来检查它们是否相等,直到BX不再在第一行)。当我运行它时,当我按w时它没有响应。

proc up
    mov ah, 0
    mov al, ' '
    mov [es:si], ax
    
    sub si, 80*2
    mov ah, 156
    mov al, '*'
    mov [es:si], ax
  ret
endp up

字符串
我试着用cmp

proc up
    mov ah, 0
    mov al, ' '
    mov [es:si], ax
    
        mov bx, 0
check:
    cmp bx, 80*2
    jz move
    cmp si, bx
    jz not_move
    inc bx
    jmp check
move:
    sub si, 80*2
    mov ah, 156
    mov al, '*'
    mov [es:si], ax
not_move:
  ret
endp up

noj0wjuj

noj0wjuj1#

mov bx, 0
check:            <<< does not need a loop
   cmp bx, 80*2
   jz move
   cmp si, bx
   jz not_move    <<< needs redrawing because of unconditional wipe
   inc bx         <<< faster with `add bx,2`
   jmp check

字符串
任何可能存在于80 x25文本屏幕顶行的字符都必须位于列表{0,2,4,... 158}中的一个偶数地址。
您的 check 循环当前正在做的是验证顶行中的所有地址,即使是与SI不匹配的奇数地址。
但为什么要有一个循环?只需将SI与160进行比较,如果SI的值为160或更大,则您知道星号尚未位于第一行,因此您可以安全地向上移动。
下面是你的 up proc的修正版本。如果代码发现星号在第一行,那么要么根本不触摸屏幕(最好),要么在擦除后,先重绘而不是直接返回!

proc up
    cmp si, 160
    jb  not_move
    mov ax, 00h << 8 + ' '   ; BlackOnBlack space
    mov [es:si], ax
    sub si, 160
    mov ax, 9Ch << 8 + '*'   ; LightRedOnLightBlue asterisk
    mov [es:si], ax
not_move:
    ret
endp up


(我问老师是否需要使用cmp,他说不需要)
他是对的,因为我们可以尝试从点的当前地址减去160,而不是cmp,并检查sub指令是否产生了借用,这将对顶行中的所有地址进行,因为它们在列表{0,2,4,... 158}中。如果借用存在,我们将不会移动并保持SI原样:

proc up
    mov ax, si               ; Keeps SI unmodified in case of 'not_move'
    sub ax, 160
    jb  not_move
    mov ax, 00h << 8 + ' '   ; BlackOnBlack space
    mov [es:si], ax
    sub si, 160
    mov ax, 9Ch << 8 + '*'   ; LightRedOnLightBlue asterisk
    mov [es:si], ax
not_move:
    ret
endp up

相关问题