You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用mov ah,0 int 16h实现汇编蛇游戏的连续移动

汇编语言蛇游戏:实现无需按键的持续移动

当前你用汇编写的蛇游戏只能在按键时移动,要改成蛇持续移动、仅检测键盘缓冲区是否有指令的话,核心是把阻塞式的按键读取换成非阻塞检测,再配合主循环自动执行移动逻辑。具体改法如下:

关键修改点

  • 改用int 16h的ah=1h功能:这个功能会检测键盘缓冲区是否有按键,有按键就设置ZF=0并返回按键码,没有则ZF=1,不会阻塞程序运行。
  • 重构主循环:每次循环先检测按键(处理方向切换),然后根据当前dir变量执行对应移动,调用延迟函数后再进入下一轮循环。
  • 修复代码笔误:原代码中a:标签里的mov [byte ptr di], 3应该是mov [byte ptr dir], 3,之前写错了操作对象。

修改后的核心循环代码

main_loop:
    ; 非阻塞检测键盘
    mov ah, 1h
    int 16h
    jz no_key_press  ; 没按键就直接执行移动

    ; 有按键就读取并处理
    mov ah, 0h
    int 16h
    mov [byte ptr saveal], al
    
    cmp [byte ptr saveal], 'w'
    jz set_dir_up
    cmp [byte ptr saveal], 'a'
    jz set_dir_left
    cmp [byte ptr saveal], 's'
    jz set_dir_down
    cmp [byte ptr saveal], 'd'
    jz set_dir_right
    cmp [byte ptr saveal], 'q'
    jmp exit

set_dir_up:
    mov [byte ptr dir], 1
    jmp move_snake
set_dir_down:
    mov [byte ptr dir], 2
    jmp move_snake
set_dir_left:
    mov [byte ptr dir], 3
    jmp move_snake
set_dir_right:
    mov [byte ptr dir], 4
    jmp move_snake

no_key_press:
    ; 没有按键时,按当前方向移动
move_snake:
    cmp [byte ptr dir], 1
    jz do_up
    cmp [byte ptr dir], 2
    jz do_down
    cmp [byte ptr dir], 3
    jz do_left
    cmp [byte ptr dir], 4
    jz do_right
    jmp main_loop  ; 初始方向没设置时,循环等待按键

do_up:
    call up
    jmp delay_and_loop
do_down:
    call down
    jmp delay_and_loop
do_left:
    call left
    jmp delay_and_loop
do_right:
    call right
    jmp delay_and_loop

delay_and_loop:
    call delay
    jmp main_loop

完整修改后的代码

MODEL small
STACK 100h
DATASEG
; --------------------------
; 变量定义
; --------------------------
saveal db ' '
dir db 0       ; 方向变量:1=上,2=下,3=左,4=右

app dw 0       ; 苹果位置
st_am dw 3
stars dw 0, 0, 0  ; 蛇身各段位置

CODESEG
proc black
body:
    mov [es:si], ax
    add si, 2
    cmp si, 25*80*2
    jnz body
  ret
endp black

proc up
    mov di, 80*2
    cmp si, di
    jb not_move_up
    
    cmp si, [app]
    jnz move_up
    call apple
    
move_up:
    call delete
    call replace_stars

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

    mov di, (24*80*2)-1
    cmp si, di
    jg not_move_down
    
    cmp si, [app]
    jnz move_down
    call apple
    
move_down:
    call delete
    call replace_stars
    
    add si, 80*2
    mov ah, 156
    mov al, '*'
    mov [es:si], ax
    mov [stars], si
    
not_move_down:
  ret
endp down
proc left

    mov dx, 0
    mov bx, si
    mov ax, si
    mov si, 80*2
    div si
    mov si, bx
    cmp dx,0
    jz not_move_left
    
    cmp si, [app]
    jnz move_left
    call apple
    
move_left:
    call delete
    call replace_stars
    
    sub si, 2
    mov ah, 156
    mov al, '*'
    mov [es:si], ax
    mov [stars], si
    
not_move_left:
  ret
endp left
proc right

    mov dx, 0
    mov bx, si
    mov ax, si
    mov si, 80*2
    div si
    mov si, bx
    cmp dx,158
    jz not_move_right
    
    cmp si, [app]
    jnz move_right
    call apple
    
move_right:
    call delete
    call replace_stars
    
    add si, 2
    mov ah, 156
    mov al, '*'
    mov [es:si], ax
    mov [stars], si
    
not_move_right:
  ret
endp right

proc apple
    mov ax, 40h
    mov es, ax
    mov ax, [es:6ch]
    and ax, 0000001111111110b
    mov di,ax
    mov [app], di
    mov ax, 0b800h
    mov es, ax
    
    mov al, '@'
    mov ah, 154
    mov [es:di], ax
  ret 
endp apple
    
proc delete
    mov bx, offset stars
    mov di, [st_am]
    dec di
    shl di, 1
    mov di, [bx+di]
    mov ax, 0b800h
    mov es, ax
    
    mov al, ' '
    mov ah, 0
    
    mov [es:di], ax
  ret
endp delete

proc replace_stars
    mov  bx, [st_am]   ; 蛇身长度(初始3)
    dec  bx
    shl  bx, 1         ; 计算最后一段的偏移
replace:
    mov  ax, [stars+bx-2]
    mov  [stars+bx], ax
    sub  bx, 2
    jnz  replace
  ret
endp replace_stars

proc first_3_dots
    mov bx, offset stars
    mov si, ((12*80+40)*2)-2
    mov al, '*'
    mov ah, 156
    mov [es:si], ax
    mov [bx], si
    mov si, (12*80+40)*2
    mov al, '*'
    mov ah, 156
    mov [es:si], ax
    mov [bx+2], si
    mov si, ((12*80+40)*2)+2
    mov al, '*'
    mov ah, 156
    mov [es:si], ax
    mov [bx+4], si
  ret
endp first_3_dots

proc delay
    mov cx, 0FFFFh
delay1:
    mov ax, 300
delay2:
    dec ax
    jnz delay2
    loop delay1
  ret
endp delay

proc incS
    
  ret
endp incS

start:
    mov ax, @data
    mov ds, ax
; --------------------------
; 初始化代码
; --------------------------
    mov ax, 0b800h
    mov es, ax
    
    mov si,0
    mov al, ' '
    mov ah, 0
    call black
    
    call first_3_dots
    mov si, ((12*80+40)*2)-2    

    call apple
    
; --------------------------
; 主循环
; --------------------------
main_loop:
    ; 非阻塞检测键盘
    mov ah, 1h
    int 16h
    jz no_key_press  ; 无按键则直接移动

    ; 有按键就读取并处理
    mov ah, 0h
    int 16h
    mov [byte ptr saveal], al
    
    cmp [byte ptr saveal], 'w'
    jz set_dir_up
    cmp [byte ptr saveal], 'a'
    jz set_dir_left
    cmp [byte ptr saveal], 's'
    jz set_dir_down
    cmp [byte ptr saveal], 'd'
    jz set_dir_right
    cmp [byte ptr saveal], 'q'
    jmp exit

set_dir_up:
    mov [byte ptr dir], 1
    jmp move_snake
set_dir_down:
    mov [byte ptr dir], 2
    jmp move_snake
set_dir_left:
    mov [byte ptr dir], 3
    jmp move_snake
set_dir_right:
    mov [byte ptr dir], 4
    jmp move_snake

no_key_press:
    ; 无按键时按当前方向移动
move_snake:
    cmp [byte ptr dir], 1
    jz do_up
    cmp [byte ptr dir], 2
    jz do_down
    cmp [byte ptr dir], 3
    jz do_left
    cmp [byte ptr dir], 4
    jz do_right
    jmp main_loop  ; 初始方向未设置时,循环等待按键

do_up:
    call up
    jmp delay_and_loop
do_down:
    call down
    jmp delay_and_loop
do_left:
    call left
    jmp delay_and_loop
do_right:
    call right
    jmp delay_and_loop

delay_and_loop:
    call delay
    jmp main_loop
    
exit:
    mov ax, 4c00h
    int 21h
END start

内容的提问来源于stack exchange,提问作者yarden

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.30 17:05:54