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

TASM鼠标左键等待函数二次调用复用前次返回值异常排查

问题根因

你的WaitForLeftClick过程存在两个核心逻辑缺陷,直接导致第二次及之后调用异常:

  1. 轮询逻辑只检测「左键当前是否按下」,没有等待完整的点击动作。int 33h的ax=3功能仅返回鼠标实时状态,不会自动清除按键标记。第一次调用时,初始状态左键是松开的,所以会正常阻塞到你按下左键再返回;但CPU执行后续判断、跳回Valid_Press第二次调用函数的速度是纳秒级,远快于人手动松开鼠标的速度(哪怕你觉得自己点得很快,加上机械按键的抖动,第一次的按下状态会残留几毫秒到几十毫秒),第二次进入函数第一次调用int 33h就会检测到左键仍处于按下状态,直接返回,根本没有等待新的点击。
  2. 过程没有遵循寄存器保护约定,也没有固定返回的坐标值。原过程直接修改ax、bx寄存器,且没有在检测到点击时锁定坐标,等后续逻辑读到cx、dx时,可能已经被其他代码修改,或者因为轮询期间鼠标移动导致坐标不准,看起来就像复用了前一次的返回值。
排查与修复方案

按以下步骤排查修复即可:

  • 先在WaitForLeftClick入口处加断点,观察第二次进入函数后第一次执行int 33h返回的bx值,如果bx最低位直接是1,就能确认是残留按键状态导致的问题。
  • 重写WaitForLeftClick的轮询逻辑,完整覆盖「等待之前的按键松开→等待新的左键按下→保存点击坐标→等待本次按键松开」的全流程,确保一次调用只响应一次完整点击,不会残留状态给下一次调用。
  • 给过程添加寄存器保护,进过程时把要修改的寄存器压栈,返回前出栈恢复,避免污染上层逻辑的寄存器值。

修正后的过程参考代码:

; 提前在数据段定义两个字变量存储点击坐标
; LastClickX dw ?
; LastClickY dw ?

proc WaitForLeftClick
    push ax
    push bx
WaitPreRelease:
    mov ax, 3
    int 33h
    test bx, 00000001b
    jnz WaitPreRelease ; 先等待残留的按下状态完全释放
WaitPress:
    mov ax, 3
    int 33h
    test bx, 00000001b
    jz WaitPress ; 轮询阻塞直到左键按下
    ; 锁定按下瞬间的坐标,避免后续松开阶段鼠标移动导致坐标偏差
    mov [LastClickX], cx
    mov [LastClickY], dx
WaitPostRelease:
    mov ax, 3
    int 33h
    test bx, 00000001b
    jnz WaitPostRelease ; 等待本次点击的左键完全松开,防止状态残留
    ; 把锁定的坐标写回cx、dx,和原过程的返回行为保持一致
    mov cx, [LastClickX]
    mov dx, [LastClickY]
    pop bx
    pop ax
    ret
endp WaitForLeftClick

补充说明:如果不需要等待左键松开,只要检测到新的按下事件就返回,也可以在第一次检测到左键按下后,加一个短延时循环过滤掉按键抖动,再确认状态稳定后返回,但对交互类程序来说,等待完整的点击释放流程兼容性更好,不会出现连点误判。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.02 06:46:04