📄 att.txt
字号:
stack segment para stack 'stack'
db 256 dup(0)
top label word
stack ends
data segment para public 'data'
buffer db 16h dup(0)
bufpt1 dw 0 ;BUFPT1=BUFPT2,THE BUFFER IS EMPTY
bufpt2 dw 0
kbflag db 0
prompt db ' *please practise typing*',0dh,0ah,'$'
scantab db 0,0,'1234567890-=',8,0
db 'qwertyuiop[]',0dh,0
db 'asdfghjkl;',0,0,0,0
db 'zxcvbnm,./',0,0,0
db ' ',0,0,0,0,0,0,0,0,0,0,0,0,0
db '789-456+1230.'
even
oldcs9 dw ?
oldip9 dw ?
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.'
crlf db 0dh,0ah,'$'
colon db ':','$'
even
saddr dw str1,str2,str3,str4,str5
count dw 0
sec dw 0
min dw 0
hours dw 0
save_lc dw 2 dup(?)
data ends
code segment
assume cs:code,ds:data,es:data,ss:stack
main proc far
start:
mov ax,stack ; 建立堆栈
mov ss,ax
mov sp,offset top
push ds ; 保存DS
sub ax,ax
push ax
mov ax,data ; 设置DS到数据段
mov ds,ax
mov es,ax
;mov ah,0
;mov al,4
;int 21h
;mov ah,0bh
;mov bh,0
;mov bl,4
;int 11h
; 将原中断向量保存在堆栈中或自设的存储单元中
mov ah,35h ; 取中断向量的功能调用
mov al,09h ;采用09类型的中断来取得输入字符
int 21h ;段址入ES,偏址放入BX
mov oldcs9,es ;保存段地地址
mov oldip9,bx ;保存偏移地址
push ds ;保存DS
mov dx,seg kbint;Of kbint
mov ds,dx
mov dx,offset kbint
mov al,09h
mov ah,25h
int 21h
pop ds
mov ah,35h ;保存中断向量
mov al,1ch ;取系统时间
int 21h
mov save_lc,bx
mov save_lc+2,es
push ds ; 设置中断向量
mov dx,seg clint
mov ds,dx
mov dx,offset clint
mov al,1ch
mov ah,25h
int 21h
pop ds
; 允许键盘和定时器中断
in al,21h ;Clear kbd & timer
and al,11111100b
out 21h,al
first: mov ah,0 ;设置文本框模式
mov al,3 ;80*25 彩色文本
int 10h
mov dx,offset prompt
mov ah,9 ;显示KBD信息
int 21h
mov si,0
next: mov dx,saddr[si] ;显示句子
mov ah,09h
int 21h
mov count,0 ;初始化向量
mov sec,0
mov min,0
mov hours,0
sti ;设置IF标志
forever:
call kbget ;等待输入字符
test kbflag,80h
jnz endint
push ax
call dispchar ;显示字符
pop ax
cmp al,0dh
jnz forever
mov al,0ah
call dispchar ;显示 CR/LF
call disptime ;显示打字时间
lea dx,crlf ;显示 CR/LF
mov ah,09h
int 21h
add si,2 ;更新指针
cmp si,5*2 ;结束句子
jne next ;否,跳转到NEXT
jmp first ;是,跳转到FIRST
endint: cli ;结束打字
push ds
mov dx,save_lc
mov ax,save_lc+2
mov ds,ax
mov al,1ch ;重置中断向量
mov ah,25h ;调用 lch
int 21h
pop ds
push ds
mov dx,oldip9
mov ax,oldcs9
mov ds,ax
mov al,09h ; 重置中断向量
mov ah,25h ;调用 09H
int 21h
pop ds
sti
ret ;返回 DOS
main endp
clint proc near
push ds ;保存ROM数据区
mov bx,data ;设置数据段
mov ds,bx
lea bx,count
inc word ptr[bx] ;计数
cmp word ptr[bx],18
jne return
call inct ;更新 sec 和 min
adj:
cmp hours,12 ;更新时间
jle return
sub hours,12
return:
pop ds
sti
iret ;中断返回
clint endp
inct proc near ;更新 sec 和min
mov word ptr[bx],0
add bx,2
inc word ptr[bx]
cmp word ptr[bx],60
jne exit
call inct
exit: ret
inct endp ;返回clint
disptime proc near ;显示时间 min:sec:msec
mov ax,min
call bindec ;显示 min
mov bx,0 ;显示 ‘:’
mov al,':'
mov ah,0eh
int 10h
mov ax,sec ;显示 sec
call bindec
mov bx,0
mov al,':' ; 显示 ‘:’
mov ah,0eh
int 10h
mov bx,count ;计数到 ms
mov al,55d
mul bl
call bindec ;显示 ms
ret ;显示main
disptime endp
bindec proc near ;Subroutine to convert binary in AX to
decimal
mov cx,100d
call decdiv
mov cx,10d
call decdiv
mov cx,1
call decdiv
ret ;返回显示时间
bindec endp
;Sub_subroutine divide number in AX by CX
decdiv proc near
mov dx,0 ;高位置0
div cx
mov bx,0
add al,30h ;转化为 ASCII
mov ah,0eh ;显示功能
int 10h
mov ax,dx
ret ;返回 BINDEC
decdiv endp
kbget proc near
push bx
cli ;中断返回
mov bx,bufpt1 ;置初始指针
cmp bx,bufpt2 ;检测 buffer是否为空
jnz kbget2 ;No,获取字符
cmp kbflag,0
jnz kbget3
sti ;允许中断
pop bx
jmp kbget ;Loop until something in buff
kbget2:
mov al,[buffer+bx] ;获取 ascii 代码
inc bx ;Inc a buffer pointer
cmp bx,16h ;At end of buffer
jc kbget3 ;No,继续
mov bx,0 ;重置 buf 开始
kbget3:
mov bufpt1,bx ;保存
pop bx
ret ;返回 main
kbget endp
;Keyboard interrupt routine
kbint proc near
push bx
push ax
in al,60h ;读取字符
push ax ;保存
in al,61h ;Get the control port
or al,80h ;Set acknowledge bit for kbd
out 61h,al
and al,7fh ;Reset acknowledge bit
out 61h,al
pop ax ;Recover scan code
test al,80h ;Is press or release code
jnz kbint2 ;Is release code,return
mov bx,offset scantab
xlat scantab ;Ascii code to AL
cmp al,0
jnz kbint4
mov kbflag,80h
jmp kbint2
kbint4:
mov bx,bufpt2 ;Buffer 的尾指针
mov [buffer+bx],al ;ASCII 放入 buffer
inc bx
cmp bx,16h ; buffer是否到结束
jc kbint3 ;No
mov bx,0 ;重置 buf 开始
kbint3:
cmp bx,bufpt1 ; buffer是否满
jz kbint2
mov bufpt2,bx ;保存 buf尾指针
kbint2: cli
mov al,20h ;中断结束
out 20h,al
pop ax
pop bx
sti
iret ;返回中断
kbint endp ;子程序dispchar:调用BIOS显示功能(INT 10H)显示键入的字符。
dispchar proc near ;(AL)=显示字符
push bx
mov bx,0
mov ah,0eh ;显示功能
int 10h ;Call video routine
pop bx
ret
dispchar endp
code ends ;代码段结束
end start
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -