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

x86-16 MBR引导加载器中BIOS读字符宏仅生效一次问题排查

Pong游戏MBR引导加载器按键无响应问题排查与解决

问题分析

你的代码中按下‘s’键仅首次触发球拍绘制,后续无响应,核心问题出在宏的跳转逻辑和键盘输入处理两个方面:

  1. 宏的非法跳转截断后续代码
    drawRacket宏的.fim1标签中使用jmp mainLoop,会直接跳出宏和moveDown函数,导致moveDown中更新playerPosition的代码完全无法执行——球拍位置从未改变,自然看不到后续移动效果。

  2. 键盘缓冲区未清空
    使用int 16h ah=01h仅检查键盘缓冲区是否有输入,不会读取/清空缓冲区。首次按下‘s’后,字符会一直留在缓冲区,后续每次检查都会重复触发moveDown,但因为位置未更新,视觉上无变化。

解决方案

1. 修复宏的跳转逻辑

将宏内的jmp mainLoop改为跳转到宏内部的结束标签,确保宏执行完毕后回到调用点继续执行后续代码:

%macro drawRacket 2
    
    mov ah, 0ch ; 像素绘制模式
    mov dx, %2

    for1:
        mov bx, 32 ; 球拍高度
        add bx, %2
        cmp dx, bx  ; 判断是否到达球拍底部
        je .fim1
        mov cx, %1  ; 球拍起始列
        jmp .for2

        .fim1:
        jmp .endMacro ; 跳转到宏结束标签,而非直接回主循环

        ; 绘制单行像素的循环
        .for2:
        mov bx, 8 ; 球拍宽度
        add bx, %1
        cmp cx, bx   ; 判断是否到达球拍右侧
        je .fim2
        mov al, 0x0f ; 白色像素
        mov ah, 0ch
        int 10h
        inc cx
        jmp .for2

        .fim2:
        inc dx
        jmp for1

    .endMacro: ; 新增宏结束标签
%endmacro

2. 修复键盘输入处理

检测到输入后,使用int 16h ah=00h读取字符以清空缓冲区,避免重复触发相同操作:

mainLoop:
    mov ah, 01h
    int 16h
    jz mainLoop ; 无输入则循环等待

    ; 读取字符,清空键盘缓冲区
    mov ah, 00h
    int 16h

    cmp al, 115 ; 's'键的ASCII码
    je moveDown
    jmp mainLoop

3. 优化:清除旧球拍(可选)

每次移动前清除旧位置的球拍,避免画面叠加混乱。新增clearRacket宏,并在moveDown中先清旧再绘新:

; 清除指定位置的球拍(用黑色像素覆盖)
%macro clearRacket 2
    mov ah, 0ch ; 像素绘制模式
    mov dx, %2
    mov al, 0x00 ; 黑色像素

    for1_clear:
        mov bx, 32 ; 球拍高度
        add bx, %2
        cmp dx, bx
        je .fim1_clear
        mov cx, %1
        jmp .for2_clear

        .fim1_clear:
        jmp .endMacro_clear

        .for2_clear:
        mov bx, 8 ; 球拍宽度
        add bx, %1
        cmp cx, bx
        je .fim2_clear
        mov ah, 0ch
        int 10h
        inc cx
        jmp .for2_clear

        .fim2_clear:
        inc dx
        jmp for1_clear

    .endMacro_clear:
%endmacro

修改moveDown函数:

moveDown:
    clearRacket 10, word[playerPosition] ; 清除旧位置球拍
    mov ax, word[playerPosition]
    inc ax
    mov word[playerPosition], ax ; 更新位置
    drawRacket 10, word[playerPosition] ; 绘制新位置球拍
    jmp mainLoop

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.24 04:45:42