如何在汇编中实现VGA模式双人Tron游戏?寄存器使用困惑求解
问题:汇编语言实现双人VGA Tron游戏的寄存器冲突问题
我想在汇编语言中制作一款VGA模式的双人Tron游戏:玩家1通过方向键控制,绘制橙色轨迹;玩家2通过W/A/S/D键控制,绘制蓝色轨迹。我已有单人游戏代码,但不清楚如何实现双人模式——我知道不宜为两名玩家使用相同寄存器,却不确定该改用哪些寄存器。我尝试用BX替代DX作为玩家2的寄存器,但似乎无效。
以下是完整代码:
Code Segment assume CS:Code, DS:Data, SS:Stack Start: mov ax, Code mov DS, AX Menu: ;Screen clear mov ax, 03h int 10h ;Kurzor position mov ah, 02h mov bh, 0 mov dh, 10 ;row mov dl, 30 ;column int 10h ;Menu mov dx, offset gamestart mov ah, 09 int 21h mov dx, offset empty mov ah, 09 int 21h mov dx, offset exit mov ah, 09 int 21h ;Wait for button press xor ax, ax int 16h ;Examine pressed button cmp al, '1' jz Startgame cmp al, '2' jz Program_End_Helper Startgame: ;First player pos mov dl, 100 mov dh, 100 push dx ;Second player pos mov dl, 200 mov dh, 100 push dx mov ax, 13h ;Change mode (VGA) int 10h mov ax, 0a000h ;Video mov es, ax ;Extra segment Draw: pop dx ;dx contains Y(dh) and X(dl) xor ah, ah mov al, dh ;ax-ben Y koordináta push dx ;dx mentése, mul utasítás felülírja mov bx, 128 ;320 mul bx ;Y koordináta * 320 pop dx ;dx-ben Y(dh), X(dl) koordináta add al, dl ;X koordináta hozzáadása jnc Pixel inc ah ;van átvitel Pixel: push dx mov di, ax mov al, 1 ;blue shl al, 2 or al, 20 ;green shl al, 2 or al, 50 ;red mov es:[di], al ;video Draw2: pop dx xor ah, ah mov al, dh push dx mov bx, 320 mul bx pop dx add al, dl jnc Pixel2 inc ah Pixel2: push dx mov di, ax mov bl, 128 mov es:[di], bl Var: xor ah, ah int 16h cmp al, 27 jz Program_End_Helper2 cmp ah, 75 jz Left cmp ah, 77 jz Right cmp ah, 72 jz Up cmp ah, 80 jz Down jmp Var Program_End_Helper: jmp Program_End Var2: ;Second player control: w,a,s,d xor ah, ah int 16h cmp al, 27 jz Program_End_Helper2 cmp al, 'a' jz Left2 cmp al, 'd' jz Right2 cmp al, 'w' jz Up2 cmp al, 's' jz Down2 jmp Var2 Left: pop dx dec dl cmp dl, 1 jnc Store inc dl jmp Store Right: pop dx inc dl cmp dl, 250 jc Store dec dl jmp Store Up: pop dx dec dh cmp dh, 1 jnc Store inc dh jmp Store Down: pop dx inc dh cmp dh, 200 jc Store dec dh jmp Store Store: push dx jmp Draw Program_End_Helper2: jmp Program_End Left2: pop dx dec dl cmp dl, 1 jnc Store2 inc dl jmp Store2 Right2: pop dx inc dl cmp dl, 250 jc Store2 dec dl jmp Store2 Up2: pop dx dec dh cmp dh, 1 jnc Store2 inc dh jmp Store2 Down2: pop dx inc dh cmp dh, 200 jc Store2 dec dh jmp Store2 Store2: push dx jmp Draw2 Program_End: mov ax, 03h int 10h pop dx mov ax, 4c00h int 21h gamestart: db '1. Start game$' empty: db ' $' exit: db '2. Exit$' Code Ends Data Segment Data Ends Stack Segment Stack Ends End Start
解决方案
你的核心问题在于没有为两名玩家独立存储位置数据,而是复用了DX寄存器和栈空间,导致两个玩家的坐标互相覆盖。另外,当前代码的输入处理是阻塞式的(int 16h等待按键),无法同时响应两名玩家的操作,这也是双人模式的关键障碍。下面分步骤修正:
1. 为两名玩家分配独立的存储位置
不要用栈临时存坐标,直接在Data段定义两个变量分别存储玩家1和玩家2的(X,Y)坐标:
Data Segment Player1X db 100 ; 玩家1X坐标 Player1Y db 100 ; 玩家1Y坐标 Player2X db 200 ; 玩家2X坐标 Player2Y db 100 ; 玩家2Y坐标 Data Ends
这样就彻底避免了寄存器冲突,每个玩家的位置都有独立的存储单元。
2. 重构绘制逻辑,分别处理两名玩家
修改绘制代码,直接从数据段读取对应玩家的坐标,而非从栈中弹出:
玩家1绘制代码:
DrawPlayer1: ; 计算显存地址: Y*320 + X xor ax, ax mov al, [Player1Y] mov bx, 320 mul bx mov cl, [Player1X] add ax, cx mov di, ax ; 设置橙色(保留你原代码的颜色计算) mov al, 1 ; blue shl al, 2 or al, 20 ; green shl al, 2 or al, 50 ; red mov es:[di], al ret
玩家2绘制代码:
DrawPlayer2: xor ax, ax mov al, [Player2Y] mov bx, 320 mul bx mov cl, [Player2X] add ax, cx mov di, ax ; 设置蓝色(VGA模式下128对应蓝色) mov al, 128 mov es:[di], al ret
3. 非阻塞式输入处理,同时响应两名玩家
原来的int 16h是阻塞调用,必须改成非阻塞检查(使用ah=01h的int 16h),这样可以在没有按键时继续执行游戏逻辑,同时检测两名玩家的输入:
GameLoop: ; 先绘制两名玩家的当前位置 call DrawPlayer1 call DrawPlayer2 ; 非阻塞检查键盘输入 mov ah, 01h int 16h jz NoKeyPressed ; 无按键则跳过处理 ; 读取按键 xor ah, ah int 16h ; 处理玩家1的方向键 cmp ah, 75 ; 左箭头 jz Player1Left cmp ah, 77 ; 右箭头 jz Player1Right cmp ah, 72 ; 上箭头 jz Player1Up cmp ah, 80 ; 下箭头 jz Player1Down ; 处理玩家2的WASD cmp al, 'a' jz Player2Left cmp al, 'd' jz Player2Right cmp al, 'w' jz Player2Up cmp al, 's' jz Player2Down ; 处理ESC退出 cmp al, 27 jz Program_End NoKeyPressed: ; 加延时防止游戏速度过快 mov cx, 0001h mov dx, 8000h mov ah, 86h int 15h jmp GameLoop
4. 重构移动逻辑,操作对应玩家的坐标
以玩家1左移为例,直接修改数据段变量:
Player1Left: dec [Player1X] cmp [Player1X], 0 jge Player1MoveDone mov [Player1X], 319 ; 边界循环,也可改成禁止越界 Player1MoveDone: jmp GameLoop
其他方向和玩家2的移动逻辑以此类推,无需再依赖栈和DX寄存器。
5. 修复原代码中的错误
- 原
Draw段中mov bx,128是笔误,应该是320(VGA 320x200模式每行像素数),否则显存地址计算完全错误。 - 栈的使用逻辑混乱,两名玩家的坐标入栈后弹出会互相覆盖,使用数据段变量是更可靠的方案。
将这些修改整合到代码中,即可实现正常的双人Tron游戏模式。
内容的提问来源于stack exchange,提问作者tomiwind
相关产品推荐
相关产品推荐

