1. 预备知识
- 在 CMOS RAM 中,存放着当前的系统时间信息。年、月、日、时、分、秒,这六个信息的长度都是 1 个字节,分别对应于第 9、8、7、4、2、0 个存储单元。
- 这些信息以 BCD 码的方式存放,每个 BCD 码以 4 位二进制表示,即每位时间信息需要 2 个 BCD 码存储,高 4 位表示十位、低 4 位表示个位。
- 如,在屏幕上显示当前系统时间中的年份:
assume cs:code
code segment
start:
mov al,9 ;年
out 70h,al ;传入9号单元的地址
in al,71h ;取9号单元的内容,高4位为十位、低4位为各位
mov ah,al
mov cl,4
shr ah,cl ;高4位
and al,00001111b ;低4位
add ah,30h
add al,30h ;转换为十进制的ASCII码值
mov bx,0b800h
mov es,bx
mov es:[160*12+40*2],ah
mov byte ptr es:[160*12+40*2+1],2h
mov es:[160*12+40*2+2],al
mov byte ptr es:[160*12+40*2+3],2h
mov ax,4c00h
int 21h
code ends
end start
程序运行结果:
2. 实验任务
编程:以年/月/日 时:分:秒的格式,显示当前的日期、时间。
预备知识展现了在屏幕中显示当前的年信息,实验要求以特定格式显示所有时间信息,依次传入不同端口地址,读取不同端口信息即可获得当前的时间信息。结合预备知识,逐步获取时间字段然后存入实验要求的格式即可。为了简化程序,本文使用子程序调用简化字符的显示。首先,数据段存放端口地址和中间字符:
data segment
db '9/8/7 4:2:0' ;数据段存放端口地址和中间字符
data ends
配合 jmp 指令判断当前字符是否为数字,如果为数字则根据该数字去对应 CMOS 单元读取时间,否则直接显示,数字的 ASCII 码值的范围为 [48, 57]:
mov cl,ds:[si] ;取字符
cmp cl,48
jb show_ch ;ASCII码值小于48则转移至show_ch
cmp cl,57
ja show_ch ;ASCII码值大于57则转移至show_ch
call get_ch ;根据端口地址取对应单元的内容
如果当前字符为数字,则读取 CMOS 对应单元的内容:
sub cl,48 ;字符转换为整数
mov al,cl ;传入指定端口号
out 70h,al
in al,71h ;取对应端口的内容,高4位为十位、低4位为个位
mov ah,al
mov cl,4
shr ah,cl ;高4位
and al,00001111b ;低4位
add ah,30h ;转换为十进制的字符形式
mov es:[bx+di],ah
mov byte ptr es:[bx+di+1],2h ;显示十位
add di,2 ;偏移2个字节写字符
add al,30h ;转换为十进制的字符形式
mov es:[bx+di],al
mov byte ptr es:[bx+di+1],2h ;显示各个位
add di,2 ;偏移2个字节写字符
inc si ;偏移1个字节取字符
ret ;子程序返回
show_ch 用于显示连接字符。显示区域为 es:[bx+di],字符存放在 cl:
show_ch:
mov es:[bx+di],cl
mov byte ptr es:[bx+di+1],2h
外层使用循环次数为 11 的循环,整体代码为:
assume cs:code
data segment
db '9/8/7 4:2:0' ;数据段存放端口地址和中间字符
data ends
code segment
start:
mov ax,data
mov ds,ax ;段寄存器DS指向数据段
mov ax,0b800h
mov es,ax ;段寄存器ES指向显示缓冲区
mov bx,160*12+20*2 ;BX存放显示偏移
mov si,0
mov di,0 ;分别用于索引源段和目的段
mov cx,11 ;循环次数
s:
push cx ;保护(CX)
mov cl,ds:[si] ;取字符
cmp cl,48
jb show_ch ;ASCII码值小于48则转移至show_ch
cmp cl,57
ja show_ch ;ASCII码值大于57则转移至show_ch
call get_ch
pop cx ;恢复(CX)
loop s
mov ax,4c00h
int 21h
show_ch:
mov es:[bx+di],cl
mov byte ptr es:[bx+di+1],2h
inc si ;偏移1个字节取字符
add di,2 ;偏移2个字节写字符
pop cx ;恢复(CX)
sub cx,1
jmp far ptr s ;段间转移至s处,调用show_ch后跳过get_ch及后续代码
get_ch:
sub cl,48 ;字符转换为整数
mov al,cl ;传入指定端口号
out 70h,al
in al,71h ;取对应端口的内容,高4位为十位、低4位为个位
mov ah,al
mov cl,4
shr ah,cl ;高4位
and al,00001111b ;低4位
add ah,30h ;转换为十进制形式
mov es:[bx+di],ah
mov byte ptr es:[bx+di+1],2h
add di,2 ;偏移2个字节写字符
add al,30h
mov es:[bx+di],al
mov byte ptr es:[bx+di+1],2h
add di,2 ;偏移2个字节写字符
inc si
ret ;子程序返回
code ends
end start
程序运行结果为:
3. 总结
- 在 CMOS RAM 中,存放着当前的系统时间信息,每个时间信息用 1 个字节表示。
- 每个时间信息以 BCD 码的方式存放,每个 BCD 码以 4 位二进制表示,即每位时间信息需要 2 个 BCD 码存储,高 4 位表示十位、低 4 位表示个位。