文章目录
目录
前言
本文是王爽老师《汇编语言》(第四版) 第十四章 检测点及实验14 访问CMOS RAM 的分析及代码。
一、检测点
1.检测点14.1
(1)检测点14.1.(1)
实验任务:编程,读取CMOS RAM的2号单元的内容。
思路分析:
第一步,将要访问的地址(2H)送入地址端口,即70H端口;
第二步,从数据端口(即71H)读取相应地址(2H)的内容。
test14_1_1: ;第14章 检测点14.1(1)
;实验任务:读取CMOS RAM的2号单元的内容
mov al,2 ;2是要发送到70H地址端口的数据,表示要访问的是地址2H
out 70H,al ;将al中的数据输出到端口70H
in al,71H ;从71H号数据端口读出2号单元的内容,送入al
;读取结果: al=当前时钟分针读数
ret
(2)检测点14.1.(2)
实验任务:编程,向CMOS RAM的2号单元写入0。
思路分析:
第一步,将要访问的地址(2H)送入地址端口,即70H;
第二步,向数据端口(71H)输出数据0。
test14_1_2: ;第14章 检测点14.1(2)
;实验任务:向CMOS RAM的2号单元写入0
mov al,2 ;2是要发送给70H地址端口的数据,表示要访问的是地址2H
out 70H,al ;将al中的数据输出到地址端口70H
;mov al,0 ;0是要发送给71H数据端口的数据,表示要传送的数据是0
out 71H,al ;将al中的数据输出到数据端口71H
ret
2.检测点14.2
(1)实验任务
编程,用加法和移位指令计算ax = ax*10。
思路分析:10=2+8,因此这个计算等价于 ax *2 + ax*8 。shl是逻辑左移指令,相当于将数据*2,shr是逻辑右移指令,相当于将数据/2。
(2)实现代码
test14_2: ;第14章 检测点14.2
;编程,用加法和移位指令计算ax = ax*10
;思路: ax*10 = ax*2 + ax*8
;给定参数:ax为待计算的值
;返回:ax返回结果
mov ax,3 ;给定ax的值
;计算 ax*2
mov bx,ax ;用bx暂存待计算的数据
shl ax,1 ;ax = ax*2
mov dx,ax ;用dx暂存结果
;计算ax*8
mov cl,3 ;8是2的三次方
shl bx,cl ;ax = ax*8
;两项求和
add bx,dx
ret
二、实验14 访问CMOS RAM
1.实验任务
编程,以“年/月/日 时:分:秒”的格式,显示当前的日期、时间。
2.思路分析
(1)读取并显示月份数据
整体思路是,从单一功能入手,将功能封装为一个子程序。因此先读取一项数据,比如月份,并将它显示在屏幕上。
(程序中将显示字符属性设置为黑底绿色,是为了方便查看,也可以设置成其它属性。)
代码如下。
assume cs:code
code segment
start:
mov al,8 ;访问8号地址的数据,即月份
mov si,160*4+5*2 ;指定显示的偏移地址
call show_one ;读取数据并显示
mov ax,4c00H
int 21H
show_one: ;功能:取CMOS RAM的指定地址的一个byte型数据,并显示在屏幕指定位置
;参数:al要访问的地址;si显存的偏移地址
;返回:无
push es
push ax
push cx
push si
;从CMOS RAM的端口读取指定地址的数据
out 70H,al ;向70H地址端口输出要访问的地址号
in al,71H ;从71H数据端口读取指定地址的数据
;将数据拆分为十位与个位数字
mov ah,al
mov cl,4
shr ah,cl ;获得十位数字
and al,00001111B ;获得个位数字
;将BCD码数字转为十进制字符形式
add ah,30H
add al,30H
;在屏幕指定位置显示
mov cx,0B800H
mov es,cx
mov cl,02H ;字符显示属性
mov es:[si],ah ;显示十位数字
inc si
mov es:[si],cl ;字符显示属性
inc si
mov es:[si],al ;显示个位数字
inc si
mov es:[si],cl ;字符显示属性
pop si
pop cx
pop ax
pop es
ret
code ends
end start
(2)读取多项数据
接下来,就可以在主程序中多次调用子程序,进行数据的读取与显示,只需要向子程序提供要访问的地址号与显存段偏移地址即可。
实验任务中要使用“/”与“:”,通过查询ASCII码表得知,“/”对应2FH,“:”对应3AH。
日期时间数据对应的地址: 年9;月8;日7;时4;分2;秒0 。
代码如下。
start:
mov si,160*10+32*2 ;指定显示的偏移地址
;显示日期
mov cx,3
mov al,9
show_date:
call show_one ;读取并显示一项日期数据
add si,4
cmp al,7 ;显示“/”
je show_blank
push ax
mov al,2fH
call show_char
add si,2
pop ax ;下一项日期数据
dec al
loop show_date
show_blank:
mov al,0H ;显示“ ”
call show_char
add si,2
;显示时间
mov cx,3
mov al,4
s_show_time: ;显示一项时间数据
call show_one
add si,4
cmp al,0 ;显示“:”
je show_time_ok
push ax
mov al,3AH
call show_char
add si,2
pop ax
sub al,2
loop s_show_time
show_time_ok:
mov ax,4c00H
int 21H
3.实现代码
完整代码及效果图如下。
assume cs:code
code segment
start:
mov si,160*10+32*2 ;指定显示的偏移地址
;显示日期
mov cx,3
mov al,9
show_date:
call show_one ;读取并显示一项日期数据
add si,4
cmp al,7 ;显示“/”
je show_blank
push ax
mov al,2fH
call show_char
add si,2
pop ax ;下一项日期数据
dec al
loop show_date
show_blank:
mov al,0H ;显示“ ”
call show_char
add si,2
;显示时间
mov cx,3
mov al,4
s_show_time: ;显示一项时间数据
call show_one
add si,4
cmp al,0 ;显示“:”
je show_time_ok
push ax
mov al,3AH
call show_char
add si,2
pop ax
sub al,2
loop s_show_time
show_time_ok:
mov ax,4c00H
int 21H
show_char: ;功能:在指定位置显示一个指定的字符
;参数:al指定字符; si显存段偏移地址
;返回:无
push es
push bx
push si
mov bx,0B800H
mov es,bx
mov es:[si],al ;显示指定字符
inc si
mov es:[si],0AH ;显示字符属性
pop si
pop bx
pop es
ret
show_one: ;功能:取CMOS RAM的指定地址的一个byte型数据,并显示在屏幕指定位置
;参数:al要访问的地址;si显存的偏移地址
;返回:无
push es
push ax
push cx
push si
;从CMOS RAM的端口读取指定地址的数据
out 70H,al ;向70H地址端口输出要访问的地址号
in al,71H ;从71H数据端口读取指定地址的数据
;将数据拆分为十位与个位数字
mov ah,al
mov cl,4
shr ah,cl ;获得十位数字
and al,00001111B ;获得个位数字
;将BCD码数字转为十进制字符形式
add ah,30H
add al,30H
;在屏幕指定位置显示
mov cx,0B800H
mov es,cx
mov cl,0AH ;字符显示属性
mov es:[si],ah ;显示十位数字
inc si
mov es:[si],cl ;字符显示属性
inc si
mov es:[si],al ;显示个位数字
inc si
mov es:[si],cl ;字符显示属性
pop si
pop cx
pop ax
pop es
ret
code ends
end start
总结
本文是王爽老师《汇编语言》(第四版) 第十四章 检测点及实验14 访问CMOS RAM并显示日期和时间 的分析及代码。通过这个实验,我初步了解了如何访问端口,以及如果通过CMOS RAM端口获取当前的日期和时间。