📄 type1.asm
字号:
;二进制数变成十进制
;用于显示时间和错误个数
.486
B_CONVERT_D MACRO TIME,NN ;TIME是存放在各时间单元的数值,NN分别为100,10,1
LOCAL LAST,NEXT
MOV dl, 0
MOV CX,TIME
LAST: CMP CX,NN
JL NEXT ;(TIME)<NN转
SUB CX,NN
INC dl
JMP LAST
NEXT: ADD dl,30h
MOV ah,02h
INT 21h ;用于一位一位显示时间
ENDM
;-------------------------------------------------------------------------------
DATA SEGMENT USE16
mesg DB ' You can start your typewriting now!! '
DB 0DH,0AH,'$'
CONTINUE DB 'Press any key to continue except Esc!'
CCOUNT EQU $-CONTINUE
ERROR DB 'The number of error is :'
ESCOUNT EQU $-ERROR
ECOUNT DW 0 ;用于存放错误的个数
OLD1C DD ? ;用于保存原有的1CH型中断向量
ICOUNT DW 0 ;用于时间统计,当其值为18约为一秒
SEC DW 0
MIN DW 0
HOURS DW 0
MSEC DW 0
str1 db 'abcd efgh ijkl mnop qrst uvwx yz.'
db 0dh,0ah,'$'
str2 db 'there are some newspapers on the table.'
db 0dh,0ah,'$'
str3 db 'there are some clouds in the sky.'
db 0dh,0ah,'$'
str4 db 'she always eats her lunch at noon.'
db 0dh,0ah,'$'
str5 db 'i do not like autumn and winter.'
db 0DH,0AH,'$'
EADDR DW str1,str2,str3,str4,str5;存放例句的首地址
RANDSUM DB ? ;存放一随机数,用于随机显示例句
COUNT DW 0
DATA ENDS
CODE SEGMENT USE16
ASSUME CS:CODE,DS:DATA,ES:DATA
BEG: MOV AX,DATA
MOV DS,AX
MOV ES,AX
CLI
CALL READ1C ;保存系统的1CH型中断向量
CALL WRITE1C ;设置自编程序的1CH型中断向量
IN AL,21H ;写中断屏蔽字
AND AL,11111110B
OUT 21H,AL ;允许日时钟中断
STI
FIRST: MOV AH,0 ;清屏
MOV AL,3
INT 10H
MOV ICOUNT,0 ;初始化各时间和计数单位
MOV MIN,0
MOV SEC,0
MOV HOURS,0
MOV MSEC,0
MOV ECOUNT,0 ;存放错误的个数
MOV AH,09H ;显示提示信息
MOV DX,OFFSET mesg
INT 21H
CALL DISPCRLF
CALL RAND ;产生一个在{0,2,4,6,8}中的随机数
MOV SI,WORD PTR RANDSUM
MOV AH,09H
MOV DX,OFFSET EADDR[SI] ;随机显示一个例句
INT 21H
MOV AH,13H ;在指定位置显示错误个数提示,初始值为000
MOV AL,1
MOV BH,0
MOV BL,0eH
MOV DH,10
MOV DL,0
MOV CX,ESCOUNT
MOV BP,OFFSET ERROR
INT 10H
B_CONVERT_D ECOUNT,100
B_CONVERT_D ECOUNT,10
B_CONVERT_D ECOUNT,1
MOV BX,EADDR[SI] ;将例句的首地址给BX
DEC BX
MOV DL,0
DEC DL
INPUT: INC DL ;列数增加1,用于下次的字符输入
MOV AH,02H ;指定光标为止
MOV BH,0
MOV DH,3
INT 10H
MOV AH,01H ;输入一个字符
INT 21H
STI
CMP AL,0DH ;以回车结束,显示时间信息
JZ DISPINF
INC BX
CMP AL, BYTE PTR [BX] ;将输入字符与例句进行比较
JZ L ;相同,继续输入
INC ECOUNT
PUSH ECOUNT
CALL DISPECOUNT ;不相同,错误个数增加1
POP ECOUNT
L: JMP INPUT
DISPINF: CLI
CALL DISPCRLF
CALL DISPTIME ;显示打字多用时间
CALL DISPCRLF
MOV AH,13H
MOV AL,1
MOV BH,0
MOV BL,0AH
MOV DH,11
MOV DL,0
MOV CX,CCOUNT
MOV BP,OFFSET CONTINUE
INT 10H ;显示是否继续的提示信息
MOV AH,08H
INT 21H ;按任意键
CMP AL,1BH
JZ QUIT ;若为Esc键退出整个程序
CALL DISPCRLF
JMP FIRST ;否则进行下一例句的练习
QUIT: CALL RESET1C ;恢复1CH型中断向量
MOV AH,4CH
INT 21H
;-------------------------------------------------------------------------------
SERVICE PROC ;日时钟中断服务子程序
PUSHA
PUSH DS
MOV AX,DATA
MOV DS,AX ;重新给DS赋值
MOV BX,OFFSET ICOUNT
INC WORD PTR [BX]
CMP WORD PTR [BX],18 ;不满18,转
JNE EXIT
SUM: MOV WORD PTR [BX], 0
ADD BX,2
INC WORD PTR[BX]
CMP WORD PTR[BX],60
JNE EXIT
JMP SUM
ADJUST: CMP HOURS,12
JLE EXIT
SUB HOURS,12
EXIT: MOV AL,20H ;写中断结束命令字
OUT 20H,AL
POP DS
POPA
STI
IRET
SERVICE ENDP
;-------------------------------------------------------------------------------
READ1C PROC ;保存系统1CH型中断向量
PUSH ES
PUSH DS
MOV AX,CODE
MOV DS,AX
MOV AX,351CH
INT 21H
MOV WORD PTR OLD1C,BX
MOV WORD PTR OLD1C+2,ES
POP DS
POP ES
RET
READ1C ENDP
;-------------------------------------------------------------------------------
WRITE1C PROC ;重置新的1CH型中断向量
PUSH DS
MOV AX,CODE
MOV DS,AX
MOV DX,OFFSET SERVICE
MOV AX,251CH
INT 21H
POP DS
RET
WRITE1C ENDP
;-------------------------------------------------------------------------------
RESET1C PROC ;恢复原1CH型中断向量
MOV DX,WORD PTR OLD1C
MOV DS,WORD PTR OLD1C+2
MOV AX,251CH
INT 21H
RET
RESET1C ENDP
;-------------------------------------------------------------------------------
DISPTIME PROC ;用于显示打字所用时间
B_CONVERT_D MIN,100 ;显示分钟数
MOV MIN,CX
B_CONVERT_D MIN,10
MOV MIN,CX
B_CONVERT_D MIN,1
MOV AL,':'
MOV AH,0EH
INT 10H
B_CONVERT_D SEC,100 ;显示秒数
MOV SEC,CX
B_CONVERT_D SEC,10
MOV SEC,CX
B_CONVERT_D SEC,1
MOV AL,':'
MOV AH,0EH
INT 10H
MOV AL,55
MOV BL,BYTE PTR ICOUNT
MUL BL
MOV MSEC,AX ;将所得毫秒数放入MESC对应的内存单元
B_CONVERT_D MSEC,100 ;显示毫秒数
MOV MSEC,CX
B_CONVERT_D MSEC,10
MOV MSEC,CX
B_CONVERT_D MSEC,1
RET
DISPTIME ENDP
;-------------------------------------------------------------------------------
DISPCRLF PROC ;显示回车换行符
MOV AH,0EH ;因较频繁地使用,故将其定义为一个子程序
MOV AL,0DH
INT 10H
MOV AH,0EH
MOV AL,0AH
INT 10H
RET
DISPCRLF ENDP
;-------------------------------------------------------------------------------
DISPECOUNT PROC ;用于统计并显示输错个数
PUSHA
MOV AH,02H
MOV BH,0
MOV DH,10
MOV DL,ESCOUNT
INT 10H
B_CONVERT_D ECOUNT,100
MOV ECOUNT,CX
B_CONVERT_D ECOUNT,10
MOV ECOUNT,CX
B_CONVERT_D ECOUNT,1
POPA
RET
DISPECOUNT ENDP
;-------------------------------------------------------------------------------
RAND PROC ;用于产生一个随机数
PUSHA
PUSH DS
MOV AX,DATA
MOV DS,AX
MOV AH,2CH
INT 21H
MOV AL,DH
MOV AH,0
MOV BL,6
DIV BL ;ax/6->ax,产生0~4之间的随机数
MOV AL,AH
MOV BL,2
MUL BL ;*2
MOV WORD PTR RANDSUM,AX ;产生{0,2,4,6,8}中的数字
POP DS
POPA
RET
RAND ENDP
CODE ENDS
END BEG
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -