共同回忆一下,那过去的美好时光!
偶 N 年前写的一个 CCBIOS 键盘管理模块
==========================
;┏━━━━━━━━━━━━━━┓
;┃程序名 : KBM.ASM ┃
;┃功 能 : 键盘管理模块 ┃
;┗━━━━━━━━━━━━━━┛
.286C
Code_Seg SEGMENT PUBLIC 'CODE'
ASSUME CS:Code_Seg,DS:Code_Seg
ORG 100H
Start:
JMP Init ; 转初始化处
KBM_PSP DW 0 ; 键盘管理模块的 PSP
Old_INT_16H DW 0,0 ; 保存原 INT 16H 中断向量
FunctionNum DB 0 ; 保存 INT 16H 入口参数
InputKey DW 0 ; 保存所按的键码
KeyNum DW 0 ; 输入键码计数
InkeyBuff DB 16 DUP(0) ; 存放输入的键码,用于提示行显示
HasHZ_2 DB 0 ; 汉字第 2 码是否返回标志
HZ_2 DW 0 ; 汉字第 2 码
HZ_Num DW 0 ; 汉字重码个数
HZDispCol DW 15 ; 汉字在提示行显示起始列
DispPtr DW 0 ; 重码汉字显示指针
DispBuffer DB 1024 DUP(20H) ; 输入的汉字重码存放处
CurPageNum DW 0 ; 当前页重码个数
QuWeiCodeHI DB 0 ; 区位码之区码
QuWeiCodeLo DB 0 ; 区位码之位码
InputCol DW 6 ; 输入码在提示行显示起始列
MsgColor DB 1FH ; 提示行信息显示颜色
InputMode DB -1 ; 当前输入方式
PY_Call DW 0,0 ; 拼音码处理入口
Process DW 0
PYInstall DB 0 ; 拼音输入法安装标志
;┏━━━━━━━━━━━━━━━━━━━━━━━━┓
;┃新的 INT 16H 中断处理程序,截断 00H,01H 功能调用 ┃
;┗━━━━━━━━━━━━━━━━━━━━━━━━┛
New_INT_16H PROC FAR
CMP AH,0FFH ; 是 FFH 号功能(退出程序用)?
JNE GoOn0 ; 不是,继续
CALL RestoreInt16H ; 是,恢复原 INT 16H 中断向量,并返回 PSP
IRET
GoOn0:
CMP CS:HasHZ_2,0 ; 需返回汉字第 2 码?
JE X0 ; 否,转
CMP AH,11H ; 是测试键盘按键状态?
JE YYJ0 ; 否,转
CMP AH,01H
JNE X1
YYJ0:
MOV AX,0102H
CMP AH,AL ; 设置 ZF 标志为 0,表示有键按下,以便返回汉字第 2 码
MOV AX,WORD PTR CS:HZ_2 ; AX = 汉字第 2 码
RET 2 ; 返回
X1:
CMP AH,10H ; 是读键盘?
JE YYJ1 ; 否,转
CMP AH,00H
JNE X0
YYJ1:
MOV AX,WORD PTR CS:HZ_2 ; AX = 汉字第 2 码
MOV WORD PTR CS:HasHZ_2,0 ; 清汉字第 2 码返回标志
IRET ; 返回
X0:
MOV CS:FunctionNum,AH ; 保存 INT 16H 入口功能号
CALL CallOldInt16H ; 调用原 INT 16H
PUSHF ; 保存标志
CMP CS:FunctionNum,10H ; 是从键盘读键码?
JE IsFunction00H ; 是,转
CMP CS:FunctionNum,00H
JE IsFunction00H
POPF ; 不是,恢复标志
JMP Int16HRet ; 转退出
IsFunction00H:
POPF ; 恢复标志
MOV CS:InputKey,AX ; 保存所读的键码
CMP AX,6800H ; Alt+F1 激活区位输入法?
JNE GoOn1 ; 否,转
MOV CS:InputMode,1 ; 当前输入方式置为 1
PUSH AX ; 设置区位码处理方式
MOV AX,OFFSET CS:QuWeiProcess
MOV CS:Process,AX
POP AX
MOV CS:KeyNum,0 ; 输入键计数清 0
MOV CS:QuWeiCodeHI,0 ; 区位码之区码清 0
MOV CS:QuWeiCodeLo,0 ; 区位码之位码清 0
CALL ClearBottom ; 清提示行
CALL DispQuWeiMsg ; 显示 "区位:" 输入信息
JMP GoOn4 ; 转
GoOn1:
CMP CS:PYInstall,0 ; 拼音输入法安装?
JE GoOn2 ; 否,转
CMP AX,6900H ; Alt+F2 激活拼音输入法?
JNE GoOn2 ; 否,转
MOV CS:InputMode,2 ; 当前输入方式置为 2
PUSH AX ; 设置拼音处理方式
MOV AX,OFFSET CS:PinYinProcess
MOV CS:Process,AX
POP AX
MOV CS:KeyNum,0 ; 输入键计数清 0
MOV CS:DispPtr,0 ; 提示行显示缓冲区显示指针清 0
CALL ClearBottom ; 清提示行
CALL DispPinYinMsg ; 显示 "拼音:" 输入信息
JMP GoOn4 ; 转
GoOn2:
CMP AX,6D00H ; Alt+F6 激活版权信息?
JNE GoOn3 ; 否,转
MOV CS:InputMode,-1 ; 当前输入方式置为 -1
CALL DispRightsMsg ; 显示版权信息
JMP GoOn4 ; 转
GoOn3:
CMP CS:InputMode,-1 ; 是否在用某输入输入汉字?
JE GoOn5 ; 否,转
CALL WORD PTR CS:Process ; 是,调用某输入法处理程序
JC GoOn5 ; 所敲的键某输入法不用,转,返回该码
GoOn4:
XOR AX,AX ; 是某输入法所用的键,返回空
JMP Int16HRet ; 返回
GoOn5:
MOV AX,CS:InputKey ; 不是自己所用的键,返回该键值
Int16HRet:
RET 2 ; 返回
New_INT_16H ENDP
;┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
;┃拼音码处理,入口: AX = 所敲的键码,出口: STC..该键不用 CLC..使用该键┃
;┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
PinYinProcess PROC NEAR
PUSHA ; 保存寄存器
PUSH DS
PUSH ES
PUSH CS ; DS = ES = CS
PUSH CS
POP DS
POP ES
MOV DI,OFFSET PinYinCode ; DI 指向拼音合法键码表处
MOV CX,26+3 ; CX = 键码个数
REPNE SCASB ; 搜索所敲的键码
OR CX,CX ; 找到?
JNZ IsPinYinCode ; 是,转
JMP PinYin_STC_Ret ; 否,不用该键码,STC 退出
IsPinYinCode:
MOV DI,OFFSET InkeyBuff ; DI 指向输入键码存放处
ADD DI,KeyNum ; 加已输入键的个数
CMP AL,08H ; 是 Backspace 键?
JNZ IsAlph ; 否,转
CMP KeyNum,0 ; 输入键计数 = 0?
JNZ Z0 ; 否,转
JMP PinYin_STC_Ret ; 是,不用该 Backspace 键,STC 退出
Z0:
DEC DI ; 指针前移
MOV BYTE PTR [DI],00H ; 删除一键码
DEC KeyNum ; 输入的拼音码个数 - 1
MOV DX,InputCol ; 在提示行第 6 列
MOV BX,OFFSET InkeyBuff ; 显示输入的拼音码
MOV AL,MsgColor ; 取显示颜色
MOV CX,KeyNum ; CX = 已输入的个数
INC CX
CALL DispBottomMsg ; 显示已输入的键码
JMP PinYin_CLC_Ret ; 转,用了 Backspace 键,CLC 退出
IsAlph:
MOV [DI],AL ; 保存该键码
INC KeyNum ; 输入键计数 + 1
PUSHA
MOV DX,InputCol ; 在提示行第 6 列显示输入码
MOV BX,OFFSET InkeyBuff
MOV AL,MsgColor
MOV CX,KeyNum
CALL DispBottomMsg
POPA
CMP KeyNum,6 ; 已输入 6 个拼音码?
JE Z2 ; 是,转,需查拼音码表
CMP AL,20H ; 输入了 Space 键?
JE Z1 ; 是,转
JMP PinYin_CLC_Ret ; 否,CLC 退出
Z1:
CMP KeyNum,1 ; 输入键码计数 = 1?
JNE NotFirstSpace ; 否,转
DEC KeyNum ; 是,输入键码计数 - 1
JMP PinYin_STC_Ret ; STC,返回该 Space 键
NotFirstSpace:
MOV BYTE PTR [DI],0 ; 清除输入的 Space 键
Z2: MOV BYTE PTR [DI+1],0 ; 输入的键码末尾清 0
CALL ChangePYCode ; 查找拼音码
MOV KeyNum,0 ; 输入键计数清 0
JNC SelectCode ; 找到输入码所对应的汉字,转选择汉字处理
CALL ClearBottom ; 没找到,清提示行
CALL DispPinYinMsg ; 显示 "拼音:" 输入信息,重输入
JMP SHORT PinYin_CLC_Ret ; CLC 退出
SelectCode:
CALL SelectDisp ; 显示第 1 页汉字码
; 修改键码处理程序入口
MOV AX,OFFSET CS:SelectPYCode
MOV CS:Process,AX
JMP SHORT PinYin_CLC_Ret ; CLC 退出
PinYin_STC_Ret:
STC ; 设置进位标志返回
JMP SHORT P_Y_P_Ret
PinYin_CLC_Ret:
CLC ; 清进位标志返回
P_Y_P_Ret:
POP ES
POP DS
POPA
RET
PinYinCode DB 8,'abcdefghijklmnopqrstuvwxyz ' ; 拼音输入有效码
PinYinProcess ENDP
;┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
;┃查拼音码表,把拼音码转换成汉字码,出口: STC..没找到 CLC..找到 ┃
;┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
ChangePYcode PROC NEAR
PUSHA ; 保存各寄存器
PUSH DS
PUSH ES
MOV DI,OFFSET InkeyBuff ; DI 指向输入的拼音键码缓冲区
CALL DWORD PTR PY_Call ; 查找汉字
PUSHF ; 清输入键码缓冲区
PUSHA
PUSH ES
CLD
MOV DI,OFFSET InkeyBuff
MOV CX,16
MOV AL,0
REP STOSB
POP ES
POPA
POPF
CMP BYTE PTR [DI+1],0 ; 输入码合法?
JZ Chg_STC ; 否,转
MOV CS:DispPtr,0 ; 显示指针清 0
PUSH CS ; ES = CS
POP ES
MOV CX,[DI] ; CX = 重码个数
MOV WORD PTR [DI],0 ; 缓冲区清 0
SHR CX,8 ; 计算重码个数
MOV CS:HZ_Num,CX ; 保存
ADD DI,2 ; 调整缓冲区指针
MOV SI,DI ; SI = DI
MOV DI,OFFSET CS:DispBuffer ; DI 指向显示缓冲区
PUSHF
CLD
TransDisp: ; 传送汉字码,格式为: "2020汉2020字"
MOV AX,2020H ; 序号区
STOSW
LODSW
OR AX,8080H
ROR AX,8 ; 汉字码
STOSW
LOOP TransDisp
POPF
POP ES ; 恢复各寄存器
POP DS
POPA
CLC ; 清进位标志
RET
Chg_STC:
POP ES
POP DS
POPA ; 恢复各寄存器
STC ; 设置进位标志
RET
ChangePYCode ENDP
;┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
;┃选择汉字,入口: AX = 所敲的键码,出口: STC..该键不用 CLC..使用该键┃
;┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
SelectPYCode PROC NEAR
PUSHA ; 保存各寄存器
PUSH DS
PUSH ES
PUSH CS ; DS = ES = CS
PUSH CS
POP DS
POP ES
CALL SelectDisp ; 在提示行显示所输入的汉字
MOV CX,14 ; CX = 选择汉字码合法键码的个数
MOV DI,OFFSET PinYinSelect ; DI 指向合法的键码表处
REPNE SCASB ; 搜索
CMP CX,0 ; 搜索到?
JNZ IsSelect ; 是,转
JMP Select_STC_Ret ; 转,该键码不用,STC 退出
IsSelect:
CMP AL,']' ; 是向前翻页键?
JNZ PgDown ; 否,转
PgDown1:
ADD DispPtr,10 ; 显示指针 + 10
MOV CX,HZ_Num ; CX = 重码个数
CMP DispPtr,CX ; 显示指针与重码个数比较
JB P0 ; 小于,转显示下一页
SUB DispPtr,10 ; 否,减 10
P0:
CALL SelectDisp ; 在提示行显示所输入的汉字
JMP Select_CLC_Ret ; 用了该键,CLC 退出
PgDown:
CMP AL,' ' ; 是空格键
JZ PgDown1 ; 空格 = ]
CMP AL,'[' ; 是向后翻页键?
JNZ Sel_Digt ; 否,是数字键
CMP DispPtr,10 ; 显示指针与 10 比较
JB P1 ; 小于,不能向前翻,在当前页继续选择
SUB DispPtr,10 ; 否,向前翻页
P1:
CALL SelectDisp ; 在提示行显示所输入的汉字
JMP Select_CLC_Ret ; 用了该键,CLC 退出
Sel_Digt:
SUB AL,30H ; ASCII 数字转换成 HEX 数字
XOR AH,AH
CMP AX,CurPageNum ; 与当前显页显示的个数比较
JA Select_STC_Ret ; 大于,不用该键,STC 退出
SHL AX,2 ; 选择的序号乘 4,见显示缓冲区格式
ADD BX,2
ADD BX,AX ; BX 指向所选择的汉字码
MOV AX,[BX] ; 取该汉字码
MOV WORD PTR CS:InputKey,0 ; 清输入键码暂存
MOV WORD PTR CS:HZ_2,0 ; 清汉字第 2 码暂存
MOV BYTE PTR CS:InputKey,AL ; 先返回汉字第 1 码
MOV BYTE PTR CS:HZ_2,AH ; 置汉字第 2 码
MOV HasHZ_2,1 ; 设置汉字第 2 码未返回标志
MOV DispPtr,0 ; 显示缓冲区指针清 0
MOV KeyNum,0 ; 输入键计数清 0
; 修该键码处理程序入口
MOV AX,OFFSET CS:PinYinProcess
MOV CS:Process,AX
CALL ClearBottom ; 清提示行
CALL DispPinYinMsg ; 显示 "拼音:" 输入信息
Select_STC_Ret:
STC ; 置进位标志
POP ES ; 恢复各寄存器
POP DS
POPA
RET
Select_CLC_Ret:
CLC ; 清进位标志
POP ES ; 恢复各寄存器
POP DS
POPA
RET
PinYinSelect DB '[] 0123456789' ; 拼音输入选择码
SelectPYCode ENDP
;┏━━━━━━━━━━━━━━━━━━━━━━━━━━┓
;┃显示提示行输入的汉字,出口: BX = 当前显示页汉字首指针┃
;┗━━━━━━━━━━━━━━━━━━━━━━━━━━┛
SelectDisp PROC NEAR
PUSH AX
MOV DX,HZDispCol ; 在提示行第 6 列清汉字显示区
MOV BX,OFFSET SpaceBuff
MOV AL,MsgColor
MOV CX,40
CALL DispBottomMsg
MOV BX,10 ; 取最大字数
MOV CurPageNum,BX ; 设置当前页显示的个数
MOV CX,DispPtr ; CX = 显示指针
ADD CX,BX ; 加当前页汉字个数
CMP CX,HZ_Num ; 与重码个数比较
JBE DispMark ; 不大于,转
MOV CX,HZ_Num ; CX = 重码个数
SUB CX,DispPtr ; 减显示指针
MOV CurPageNum,CX ; 设置当前显示页汉字个数
DispMark:
MOV CX,CurPageNum ; CX = 当前显示页汉字个数
MOV BX,OFFSET DispBuffer
MOV AX,DispPtr
SHL AX,2
ADD BX,AX
PUSH BX
PUSH CX
MOV AX,3020H ; 设置序号
MarkLoop: MOV [BX],AX
ADD BX,4
INC AH
LOOP MarkLoop
MOV WORD PTR [BX],0
POP CX
POP BX
PUSH BX
PUSH CX
PUSH DX
MOV DX,HZDispCol
SHL CX,2
DispLoop:
PUSH CX
MOV AL,1EH
MOV CX,2
CMP BYTE PTR ES:[BX],0A0H
JAE DispHZ
MOV AL,1CH
DispHZ: CALL DispBottomMsg
ADD BX,2
ADD DX,2
POP CX
SUB CX,2
OR CX,CX
JNZ DispLoop
POP DX
POP CX
POP BX
; 显示剩余的汉字个数
PUSHA
MOV AX,HZ_Num ; 取重码个数
SUB AX,DispPtr ; 减去已显示的个数
SUB AX,CurPageNum ; 减去当前页显示的个数
MOV BL,100 ; 转换成 ASCII 数字
DIV BL
ADD AL,30H
MOV BYTE PTR HasNum[1],AL
XCHG AH,AL
XOR AH,AH
MOV BL,10
DIV BL
ADD AL,30H
MOV BYTE PTR HasNum[2],AL
ADD AH,30H
MOV BYTE PTR HasNum[3],AH
MOV AL,1AH ; 显示颜色
MOV BX,OFFSET HasNum ; 显示缓冲区
MOV CX,5 ; 字符个数
MOV DX,60 ; 显示起始列
CALL DispBottomMsg ; 显示
POPA
POP AX
RET
SpaceBuff DB 40 DUP(20H)
HasNum DB '[000]'
SelectDisp ENDP
;┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
;┃区位码处理,入口: AX = 所敲的键码,出口: STC..该键不用 CLC.. 使用该键 ┃
;┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
QuWeiProcess PROC NEAR
PUSHA ; 保存各寄存器
PUSH DS
PUSH ES
PUSH CS ; DS = ES = CS
PUSH CS
POP DS
POP ES
MOV DI,OFFSET QuWeiCode ; DI指向区位码字符表
MOV CX,12 ; CX = 个数
REPNE SCASB ; 搜索
OR CX,CX ; 找到?
JNZ IsQWKey ; 找到,转
JMP STC_Ret ; 否,不用该键,STC 退出
IsQWKey:
MOV DI,OFFSET InkeyBuff ; DI 指向输入键缓冲区
ADD DI,KeyNum ; DI 加已输入区位码的个数
CMP AL,08H ; 是 Backspace?
JNZ DigtKey ; 否,是数字键
CMP KeyNum,0 ; 输入的区位码个数 = 0?
JNZ Y0
JMP STC_Ret ; 是,置进位标志,表示此键不用
Y0:
DEC DI ; 指针 - 1
MOV WORD PTR [DI],2020H ; 删除键码
DEC KeyNum ; 输入的区位码个数 - 1
MOV DX,InputCol ; 在提示行第 6 列
MOV BX,OFFSET InkeyBuff ; 显示输入的区位码
MOV AL,MsgColor
MOV CX,KeyNum ; 已输入的个数
INC CX
CALL DispBottomMsg
JMP CLC_Ret ; CLC 退出
DigtKey:
MOV DH,QuWeiCodeHI ; 取区位码
MOV DL,QuWeiCodeLo
INC KeyNum ; 输入键个数 + 1
MOV [DI],AL ; 存放在输入缓冲区
SUB AL,30H ; 由 ASCII 数字转换成 BCD 数字
SHL DX,4
XOR AH,AH
ADD DX,AX
MOV QuWeiCodeHI,DH
MOV QuWeiCodeLo,DL
PUSH AX
PUSH BX
PUSH CX
PUSH DX
PUSH DI
MOV DX,InputCol ; 在提示行第 6 列显示输入码
MOV BX,OFFSET InkeyBuff
MOV AL,MsgColor
MOV CX,KeyNum
CALL DispBottomMsg
POP DI
POP DX
POP CX
POP BX
POP AX
CMP KeyNum,4 ; 够 4 个码?
JB CLC_Ret ; 没输完,继续
CMP DL,94H ; 区/位码大于 94H 或等于 0,非法码
JA InvalidCode
CMP DH,94H
JA InvalidCode
CMP DX,0
JZ InvalidCode
JMP VaildCode
InvalidCode:
MOV KeyNum,0 ; 输入的区位码不合法
MOV QuWeiCodeHI,0 ; 清区位码之区码
MOV QuWeiCodeLo,0 ; 清区位码之位码
CALL ClearBottom ; 清提示行
CALL DispQuWeiMsg ; 显示 "区位:" 输入信息
JMP CLC_Ret ; CLC 退出
VaildCode: ; 将 BCD 码转换成 HEX
CALL BCD_HEX
; 转换成汉字国标码
ADD DX,0A0A0H
MOV WORD PTR CS:InputKey,0 ; 输入键暂存清 0
MOV WORD PTR CS:HZ_2,0 ; 汉字第 2 码清 0
MOV BYTE PTR CS:InputKey,DH ; 设置汉字第 1 码,先返回
MOV BYTE PTR CS:HZ_2,DL ; 设置汉字第 2 码
MOV HasHZ_2,1 ; 设置汉字第 2 码未返回标志
MOV KeyNum,0 ; 输入键计数清 0
MOV QuWeiCodeHI,0 ; 清区位码之区码
MOV QuWeiCodeLO,0 ; 清区位码之位码
CALL ClearBottom ; 清提示行
CALL DispQuWeiMsg ; 显示 "区位:" 输入信息
STC_Ret:
STC ; 置进位标志
JMP SHORT Q_W_P_Ret
CLC_Ret:
CLC ; 清进位标志
Q_W_P_Ret:
POP ES ; 恢复各寄存器
POP DS
POPA
RET
QuWeiCode DB 8,'1234567890' ; 区位输入合法码表
QuWeiProcess ENDP
;┏━━━━━━━━━━┓
;┃将 BCD 码转换成 HEX ┃
;┗━━━━━━━━━━┛
BCD_HEX PROC NEAR
PUSH AX
PUSH CX
MOV DX_HI,DH
MOV DX_LO,DL
MOV AL,10
SHR DH,4
MUL DH
MOV DH,AL
AND DX_HI,0FH
ADD DX_HI,DH
MOV AL,10
MOV DL,DX_LO
SHR DL,4
MUL DL
MOV DL,AL
AND DX_LO,0FH
ADD DL,DX_LO
MOV DH,DX_HI
POP CX
POP AX
RET
DX_HI DB 0
DX_LO DB 0
BCD_HEX ENDP
;┏━━━━━━━┓
;┃调用原 INT 16H┃
;┗━━━━━━━┛
CallOldInt16H PROC NEAR
PUSHF
CALL DWORD PTR CS:Old_INT_16H
RET
CallOldInt16H ENDP
;┏━━━━┓
;┃清提示行┃
;┗━━━━┛
ClearBottom PROC NEAR
PUSHA
PUSH DS
PUSH ES
PUSH CS
PUSH CS
POP DS
POP ES
MOV AL,MsgColor
MOV CX,80
MOV DX,0
MOV BX,OFFSET ClearMsg
CALL DispBottomMsg
POP ES
POP DS
POPA
RET
ClearMsg DB ' ┃ Solomon '
ClearBottom ENDP
;┏━━━━━━┓
;┃显示版权信息┃
;┗━━━━━━┛
DispRightsMsg PROC NEAR
PUSHA
PUSH DS
PUSH ES
PUSH CS
PUSH CS
POP DS
POP ES
MOV AL,MsgColor
MOV CX,80
MOV DX,0
MOV BX,OFFSET RightsMsg
CALL DispBottomMsg
POP ES
POP DS
POPA
RET
RightsMsg DB ' Solomon CCBIOS Ver 1.0 - (C)1997 Solomon Software Co. Ltd. - AZMC presents '
DispRightsMsg ENDP
;┏━━━━━━━━━┓
;┃显示区位输入提示符┃
;┗━━━━━━━━━┛
DispQuWeiMsg PROC NEAR
PUSHA
PUSH DS
PUSH ES
PUSH CS
PUSH CS
POP DS
POP ES
MOV AL,MsgColor
MOV CX,5
MOV DX,0
MOV BX,OFFSET QuWeiMsg
CALL DispBottomMsg
POP ES
POP DS
POPA
RET
QuWeiMsg DB '区位:'
DispQuWeiMsg ENDP
;┏━━━━━━━━━┓
;┃显示拼音输入提示符┃
;┗━━━━━━━━━┛
DispPinYinMsg PROC NEAR
PUSHA
PUSH DS
PUSH ES
PUSH CS
PUSH CS
POP DS
POP ES
MOV AL,MsgColor
MOV CX,5
MOV DX,0
MOV BX,OFFSET PinYinMsg
CALL DispBottomMsg
POP ES
POP DS
POPA
RET
PinYinMsg DB '拼音:'
DispPinYinMsg ENDP
;┏━━━━━━━━━━━━┓
;┃恢复原 INT 16H 中断向量 ┃
;┗━━━━━━━━━━━━┛
RestoreInt16H PROC NEAR
CMP AL,01H
JE RestoreVector
MOV AX,1994
MOV BX,CS:KBM_PSP
RET
RestoreVector:
PUSH DX
PUSH DS
PUSH CS
POP DS
MOV AX,2516H
LDS DX,DWORD PTR Old_INT_16H
INT 21H
POP DS
POP DX
RET
RestoreInt16H ENDP
;┏━━━━━━━━━━━━━━┓
;┃在提示行显示字符串 ┃
;┠──────────────┨
;┃入口 : AL = 颜色 ┃
;┃ CX = 字符串长度 ┃
;┃ DX = 起始列 ┃
;┃ ES:BX = 字符串首地址 ┃
;┃出口 : 无 ┃
;┗━━━━━━━━━━━━━━┛
DispBottomMsg PROC NEAR
PUSH CX
PUSH BX
MOV BL,AL ; 设置显示颜色
MOV AX,0FF04H
INT 10H
POP BX
POP CX
MOV AX,0FF03H ; 显示字符串
INT 10H
RET
DispBottomMsg ENDP
;┏━━━━┓
;┃初始化处┃
;┗━━━━┛
Init:
PUSH CS
POP DS
MOV KBM_PSP,CS ; 存 PSP
MOV AX,356BH ; 取 INT 6BH 中断向量,即拼音输入法入口
INT 21H
; 保存
CMP BX,0040H
JNZ PPPP
MOV PYInstall,1 ; 设置拼音输入法安装标志
MOV WORD PTR PY_Call,BX
MOV WORD PTR PY_Call+2,ES
PPPP:
MOV AX,3516H ; 取 INT 16H 中断向量
INT 21H
CMP BX,OFFSET New_INT_16H ; 是否已安装?
JE HasInstall ; 是,显示已安装信息并退出
MOV Old_INT_16H,BX ; 保存原向量
MOV Old_INT_16H+2,ES
PUSH CS
POP ES
MOV AX,2516H ; 设置新的 INT 16H 中断向量
MOV DX,OFFSET New_INT_16H
INT 21H
CALL DispRightsMsg ; 显示版权信息
MOV DX,OFFSET Init ; 计算驻留长度
MOV CL,04H
SHR DX,CL
INC DX
MOV AX,3100H ; 驻留退出
INT 21H
HasInstall:
MOV AX,4CFFH ; 退出
INT 21H
Code_Seg ENDS
END Start