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

FASM汇编程序需求:仅同时按左右Shift时转换指定字母为大写

修正FASM键盘钩子程序:仅同时按左右Shift时转换小写为大写

问题分析

你的程序当前仅按右Shift就触发大写转换,核心问题有三个:

  1. Shift状态判断逻辑错误:处理字母输入时,代码先加载左Shift标志到al,随即被右Shift标志覆盖,导致只检查右Shift状态,忽略左Shift的判断。
  2. 右Shift释放码错误:右Shift的释放扫描码是0B6h(十进制182),但代码中误写为0BAh,导致右Shift释放时flagashiftp无法清零,状态异常。
  3. 释放判断分支位置错误:右Shift释放的判断分支被放在左Shift释放判断之后,导致该分支无法被正常执行,进一步加剧状态异常。

修正后的代码

format MZ
stack stk:256
entry text:main

macro delay time
{
local ext,iter,end
      push cx
      mov cx, time
ext:
     in al,60h
     cmp al,01h
     je end
     push cx
     mov cx, 0FFFFh
iter:
     loop iter
     pop cx
     loop ext
     pop cx
end:
    pop cx
}

segment data_16 use16
_stare08 dw ?
         dw ?
_stare09 dw ?
_program dw ?
params   dw ?
         dw ?
mark_08  dw 0
time_08  db 0

mark_09 dw 320
znakim db 'dfghjkl'
znakid db 'DFGHJKL'
atryb db 71h
flagashift db 0      ; 左Shift按下标志,按下设为1,释放设为0
flagashiftp db 0     ; 右Shift按下标志,按下设为1,释放设为0

segment text use16
moje08:
        push ax
        push bx
        push es
        test [time_08],03
        jnz skip
        mov ax,0B800h
        mov es,ax
        mov al,21h
        mov ah,71h
        mov bx,[mark_08]
        mov [es:bx],ax
        add [mark_08],2
skip:
        inc [time_08]
        pop es
        pop bx
        pop ax
        jmp dword [ds:_stare08]

moje09:
        push ax
        push bx
        push es
        in AL,60h

        ; 处理左Shift按下(扫描码2Ah=42)
        cmp AL,42
        jne sprawdzPrawyShift
        mov byte [ds:flagashift],1
        jmp dalej3

sprawdzPrawyShift:
        ; 处理右Shift按下(扫描码36h=54)
        cmp AL, 54
        jne sprawdzWyzwolenie
        mov byte [ds:flagashiftp], 1
        jmp dalej3

sprawdzWyzwolenie:
        ; 处理左Shift释放(扫描码AAh=170)
        cmp AL,170
        jne sprawdzWyzwoleniePrawy
        mov byte [ds:flagashift],0
        jmp dalej3

sprawdzWyzwoleniePrawy:
        ; 处理右Shift释放(扫描码B6h=182,修正原0BAh错误)
        cmp AL, 0B6h
        jne dalej3
        mov byte [ds:flagashiftp], 0

dalej3:
        cmp AL,80h
        ja dalej
        sub AL,2
        cmp AL,09h
        ja dalej1
        inc AL
        cmp AL,80h
        jne xx
        sub AL,80h

xx:     add AL,30h
yy:
        mov AH,[atryb]
        mov BX,[mark_09]
        push ax
        mov ax,0B800h
        mov es,ax
        pop ax
        mov [ES:BX],AX
        add [mark_09],2
        jmp dalej

dalej1:
        sub al,30
        cmp al,6
        ja dalej
        mov ah,0
        mov bx,znakim
        add bx,ax

        ; 修正:同时检查左右Shift是否都按下
        cmp byte [ds:flagashift], 1
        jne dalej5       ; 左Shift没按下,直接用小写
        cmp byte [ds:flagashiftp], 1
        jne dalej5       ; 右Shift没按下,直接用小写
        add bx,7         ; 两个Shift都按下,切换到大写数组

dalej5:
        mov al,[bx]
        jmp yy

dalej:
        in AL,61h
        or AL,80h
        out 61h,AL
        and AL,7Fh
        out 61h,AL

        mov AL,20h
        out 20h,AL

        pop es
        pop bx
        pop ax
        iret

main:
        mov ax,data_16
        mov ds,ax
        mov ax,stk
        mov ss,ax
        mov sp,256

        cli
        xor ax,ax
        mov es,ax
        les bx,[es:(8 shl 2)]
        mov [_stare08+2],es
        mov [_stare08],bx
        mov es,ax
        mov word[es:(8 shl 2)],moje08
        mov word[es:(8 shl 2)+2],text

        mov es,ax
        les bx,[es:(9 shl 2)]
        mov [_stare09+2],es
        mov [_stare09],bx
        mov es,ax
        mov word[es:(9 shl 2)],moje09
        mov word[es:(9 shl 2)+2],text
        sti

        delay 60000

        cli
        xor ax,ax
        les cx,dword[ds:_stare08]
        mov ds,ax
        mov [ds:(8 shl 2)],cx
        mov [ds:(8 shl 2)+2],es

        mov ax,data_16
        mov ds,ax
        les cx,dword[ds:_stare09]
        xor ax,ax
        mov ds,ax
        mov [ds:(9 shl 2)],cx
        mov [ds:(9 shl 2)+2],es

        mov ax,data_16
        mov ds,ax
        sti

        mov ah,1
        int 21h
        mov ax,4c00h
        int 21h

        ret

segment stk use16
        db 256 dup (?)

关键修改点说明

  1. 修正Shift释放码:将右Shift释放的判断cmp AL, 0BAh改为cmp AL, 0B6h,确保右Shift释放时flagashiftp能正确清零。
  2. 重构按键释放逻辑:将左Shift和右Shift的释放判断整理为独立分支,保证每个释放事件都能被处理。
  3. 修复Shift状态判断:在dalej1段,先检查左Shift是否按下,再检查右Shift是否按下,只有两者都为1时,才切换到大写字母数组(add bx,7)。
  4. 移除无效代码:删除了原代码中无意义的cmp byte [ds:flagashift], 1判断分支,以及未被使用的moje10过程。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.02 20:03:14