实验14访问CMOS RAM
编程, 以“年/月/日 时:分:秒”的格式,显示当前的日期、时间。注意:CMOS RAM中存储着系统的配置信息,除了保存时间信息的单元外,不要向其他的单元中写入内容,否则将引起一些系统错误。
我对该题分别作了三种解答,一种是自己通过分析自己写的,还有两种是借鉴了@leader4 看到的思路在此基础上写的下面是相应的程序。
;该程序为我自己构思并自己写的实验14的程序,在这个程序中我主要是用的是站,利用栈的特性(先进后出)把程序从新输出成我想要的顺序
assume cs:code
code segment
start:
mov ax, 0h
mov cx, 3h
time_1: ;因为这个程序我是把时间数据和日期数据分别输出的因为他们在CMOS RAM中排列的地址相隔字节不一样所以必须分别输出
mov bx, ax ;因为in会吧传出的数据传给al所以在这里用bx过度一下
out 70h, al
in al, 71h ;把数据从CMOS RAM芯片的相应端口输出到al中
call good_1 ;把调出来得数据从BCD码的形式转换成16位并储存在ax中
push ax ;压入栈中
mov ax, bx ;因为out和in只能使用al和ax所以在上面用bx过度一下现在从新传给ax
add ax, 2h ;把ax+2是因为时间的数据在CMOS RAM中是储存在 00 02 04中的他们相同的地方就是每个字符段中都是相隔两个字节
loop time_1
mov cx, 3h
year_1: ;日期输出,顺序和每个程序段的作用都大体相同就是偏移地址的叠加数量商有区别
inc ax ;因为时间地址最后一个是储存在04偏移地址中的二日期第一个是储存在07地址中04和07差3个字节所以上面遗留下来得两个和这个相加正好就是日期的偏移地址
mov bx, ax
out 70h, al
in al, 71h
call good_1
push ax
mov ax, bx
loop year_1
show_1: ;下面的的程序主要是输出,输出也是分为了两个程序段一个是时间单独输出,一个是日期因为他们中间存在一个/和:所以我单独输出了他们每个数据
mov ax, 0b800h
mov es, ax
mov di, 12 * 160 + 70
mov bx, 0
show_2:
pop ax
mov byte ptr es:, ah
mov byte ptr es:, 2
mov byte ptr es:, al
mov byte ptr es:, 2
cmp bx, 2
je show_3
mov byte ptr es:, '/'
add di, 6
inc bx
jmp short show_2
show_3:
add di, 2
mov bx, 0
show_4:
pop ax
add di, 6
mov byte ptr es:, ah
mov byte ptr es:, 2
mov byte ptr es:, al
mov byte ptr es:, 2
cmp bx, 2
je show_5
mov byte ptr es:, ':'
inc bx
jmp short show_4
show_5:
nop
mov ax, 4c00h
int 21h
good_1:
push cx
mov ah, al
mov cl, 4
shr ah, cl
add ah, 30h
and al, 00001111b
add al, 30h
pop cx
ret
code ends
end start
程序我分别是用int 10 第2和第9个子程序和int 21 第9子程序输出的
assume cs:code, ds:data_1, ds:data_2
data_1 segment
db 9, 8, 7, 4, 2, 0 ;这个数据段是用于定位cmos ram芯片中时间数据段中的偏移地址的,
data_1 ends
data_2 segment
db 'yy/mm/dd hh:mm:ss', 0 ;用于储存从cmos ram中调出的数据的
data_2 ends
code segment
start: ;下面的的代码段是用于从CMOS RAM芯片中通过70和71端口读取数据并把他们存入data_2中的
mov ax, data_1
mov ds, ax
mov si, 0
mov ax, data_2
mov es, ax
mov di, 0
mov cx, 6
loop_1:
mov al, byte ptr ds:
out 70h, al
in al, 71h
call good ;我把BCD码转换的程序单独写了一个函数存在了下面good标记段中用call跳转过去执行,这样我感觉看着更清晰
mov byte ptr es:, ah
mov byte ptr es:, al
add di, 3
inc si
loop loop_1
;显示data_2中的数据在屏幕上这里我用了int 10 中断中的2号子程序和9子程序
mov si, 0h
mov dl, 12 ;循环使用int 10 ah 2
show_2:
mov ah, 2
mov bh, 0
mov dh, 5
int 10h
mov ah, 9
mov bh, 0
mov al, byte ptr es:
mov bl, 2
mov cx, 1
int 10h
inc dl
inc si
;cmp byte ptr es:, 0 ;用了两种跳转方式实验感觉还是jcxz好使这个留着备用
;je loop_3
mov cx, 0
mov cl, byte ptr es:
jcxz show_3
jmp short show_2
show_3:
nop
mov ax, 4c00h
int 21h
good:
push cx
mov ah, al
mov cx, 4
shr ah, cl
add ah, 30h
and al, 00001111b
add al, 30h
pop cx
ret
code ends
end start
assume cs:code, ds:data, ds:show_x
data segment
db 9, 8, 7, 4, 2, 0
data ends
show_x segment
db 'yy/mm/dd hh:mm:ss', '
show_x ends
code segment
start: ;定位数据段把他们传给相应的寄存器
mov ax, data
mov ds, ax
mov si, 0
mov ax, show_x
mov es, ax
mov di, 0
mov cx, 6h
one_1: ;把数据从cmos ram中提取出来传给数据段show_x储存起来
mov al, ds:
out 70h, al
in al, 71h
call good_1 ;BCD转换成16进制的数据并储存在show_x中
mov byte ptr es:, ah
mov byte ptr es:, al
add di, 3
inc si
loop one_1
show_1:
mov di, 0
mov ax, 0
show_2: ;这个程序我用的是int 10 第2个子程序配上int 21 第9个子程序一起使用段输出
mov ah, 2
mov bh, 0
mov dh, 10
mov dl, 35
int 10h
mov ax, show_x ;从show_x数据段中把数据输出到屏幕上
mov ds, ax
mov dx, 0
mov ah, 9
int 21h
mov ax, 4c00h
int 21h
good_1: ;把BCD中的数据转换成16进制并储存到show_x数据段中
push cx
mov ah, al
mov cl, 4
shr ah, cl
add ah, 30h
and al, 00001111b
add al, 30h
pop cx
ret
code ends
end start
页:
[1]