FASM汇编程序需求:仅同时按左右Shift时转换指定字母为大写
修正FASM键盘钩子程序:仅同时按左右Shift时转换小写为大写
问题分析
你的程序当前仅按右Shift就触发大写转换,核心问题有三个:
- Shift状态判断逻辑错误:处理字母输入时,代码先加载左Shift标志到
al,随即被右Shift标志覆盖,导致只检查右Shift状态,忽略左Shift的判断。 - 右Shift释放码错误:右Shift的释放扫描码是
0B6h(十进制182),但代码中误写为0BAh,导致右Shift释放时flagashiftp无法清零,状态异常。 - 释放判断分支位置错误:右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 (?)
关键修改点说明
- 修正Shift释放码:将右Shift释放的判断
cmp AL, 0BAh改为cmp AL, 0B6h,确保右Shift释放时flagashiftp能正确清零。 - 重构按键释放逻辑:将左Shift和右Shift的释放判断整理为独立分支,保证每个释放事件都能被处理。
- 修复Shift状态判断:在
dalej1段,先检查左Shift是否按下,再检查右Shift是否按下,只有两者都为1时,才切换到大写字母数组(add bx,7)。 - 移除无效代码:删除了原代码中无意义的
cmp byte [ds:flagashift], 1判断分支,以及未被使用的moje10过程。
内容的提问来源于stack exchange,提问作者FireX
相关产品推荐
相关产品推荐

