汇编网首页登录博客注册
unixandlinux的学习博客
博客首页博客互动【做检测题】论坛求助

我的博客

个人首页 |  我的文章 |  我的相册 |  我的好友 |  最新访客 |  文章收藏 |  论坛提问 |  友情链接 |  给我留言  
图片载入中
学习动态
最新评论
最新留言
好友圈
友情链接

[2023-08-15 10:41] 第 14 章 实验 14  访问 CMOS RAM

实验 14 访问 CMOS RAM

编程,以“年/月/日 时:分:秒”的格式,显示当前的日期、时间。
注意:CMOS RAM 中存储着系统的配置信息,除了保存时间信息的单元外,不要向其他的单元中写入内容,否则将引起一些系统错误。

具体代码如下:

assume cs:code

; sysdt 段中 '00/00/00 ' 和 '00:00:00' 的 '00' 部分,是需要写入的数据位置。
; 以 ASCII 码值 0 作为字符串结束符。
sysdt segment
  db  '20','00/00/00 ','00:00:00',0
sysdt ends

code segment

start: mov ax,sysdt
    mov ds,ax
    mov si,2  ; ds:si 指向需要写入的首个表示年份的字符地址,即 ds:2

    mov al,9  ; 设置年、月、日数据起始参数
    mov cx,3  ; 设置 loop s0 循环次数
s0:  call rd
   add si,2
   dec al
   loop s0

   mov al,4  ; 设置时、分、秒数据起始参数
   mov cx,3  ; 设置 loop s1 循环次数
s1:  call rd
   add si,2
   sub al,2
   loop s1

   ; 输出 sysdt 段字符串到屏幕中
   mov dh,10  ; 屏幕行
   mov dl,10  ; 屏幕列
   mov cl,2  ; 字符属性:绿色字符
   mov ax,sysdt
   mov ds,ax
   mov si,0  ; ds:si 指向 sysdt 段字符串首地址
   call show_str

   mov ax,4c00h
   int 21h

; begin rd
; 功能:将 CMOS RAM 中的时间信息写入 sysdt 段字符串中
; 参数:(al) = CMOS RAM 时间信息的单元号
;    ds:si 指向需要写入数字字符的 sysdt 段内存单元
; 说明:参数 (al) 为调用 dt 子程序作准备,参数 ds:si 为调用 write 子程序作准备
rd:  push ax  ; AL 寄存器中存储着要读取的 CMOS RAM 单元号参数,AL 寄存器会在 dat 子程序中被使用而改变其存储的数据,但在主调程序中还需要使用 AL 寄存器存储的参数 —— 自减 1 或自减 2,因此需要在执行 rd 子程序功能代码之前先将其入栈保存。
   push cx  ; CX 寄存器中存储着主调程序的 loop 循环次数,CX 寄存器在 dat 子程序中会被使用而改变其存储的数据,因此需要在执行 rd 子程序功能代码之前先将其入栈保存。
   call dat
   call write

   pop cx
   pop ax
   ret
; end rd

; begin dt
; 功能:
; 1. 读取 CMOS RAM 中的时间数据
; 2. 将时间数据的十位数字的数值存储到 AH 寄存器中,个位数字的数值存储到 AL 寄存器中
; 3. 将数字的数值形式转换为字符形式
; 参数:(al) = CMOS RAM 时间信息的单元号
dat:  out 70h,al
    in al,71h  ; 将 CMOS RAM 中的年份数据
    mov ah,al  ; 年份数据的副本存储到 AH 寄存器中
    and al,00001111B  ; 截取年份数据的个位码值
    mov cl,4  ; 设置移动位值为 4:表示需要逻辑移动 4 位
    shr ah,cl  ; 逻辑右移 4 位,留存年份数据的十位码值
        ; 将数字的数值形式转换为字符形式
    add ah,30h
    add al,30h
    ret
; end dat

; begin write
; 功能:写入 sysdt 段空间,以形成字符串形式
; 参数:ds:si 指向需要写入数字字符的 sysdt 段内存单元
write:  mov [si],ah ; 将数据的十位数字字符码写入 sysdt 段的相应位置
    inc si
    mov [si],al  ; 将数据的个位数字字符码写入 sysdt 段的相应位置
    ret
; end write

; begin show_str
; 功能:通过调用 BIOS 的 int 10h 指令中断例程的 2 号和 9 号子程序来显示字符串。
; 参数:(dh)=行号  (dl)=列号  (cl)=字符属性  ds:si 指向字符串首地址
show_str:  push cx  ; 由于下面要用到 CX 寄存器,所以需将 CL 寄存器存储的字符属性信息数据入栈
      mov bp,sp  ; 为下面调用原 CL 寄存器存储的字符属性数据而作的准备,这时 ss:[bp]=(cl)

; 设置 BIOS 的 int 10h 指令中断例程的 2 号子程序参数
; 注意,行、列数据已经作为参数存储在 DX 寄存器中
dis:  mov ah,2  ; 设置 BIOS 的 int 10h 指令中断例程子程序为 2 号:设置光标位置
    mov bh,0  ; 设置显示缓冲区的第 0 页
    int 10h  ; 调用 BIOS 的 int 10h 指令以引发其中断,从而调用其中断例程的 2 号子程序

    ; 设置 BIOS 的 int 10h 指令中断例程的 9 号子程序参数
    mov al,[si]  ; 将要显示的字符传送到 AL 寄存器
    cmp al,0  ; 验证 AL 寄存器所存储的字符 ASCII 码是否为 0 —— 是否到达字符串的结束位置
    je showret  ; 执行判断字符码
    mov ah,9  ; 设置 BIOS 的 int 10h 指令中断例程的子程序为 9 号:在光标位置显示字符
    mov bl,[bp]  ; 读取字符属性信息到 BL 寄存器
    mov cx,1  ; 字符显示的重复次数为 1 次
    int 10h  ; 调用 BIOS 的 int 10h 指令以引发其中断,从而其中断例程的 9 号子程序

    inc si  ; 将 ds:[si] 指向要显示字符串的下一个字符
    inc dl  ; 增加列号,以便让下一个字符显示在屏幕的下一列位置
    jmp short dis

showret:  pop cx
      ret
; end show_str

code ends

end start
评论次数(0)  |  浏览次数(328)  |  类型(课程实验) |  收藏此文  | 
 
 请输入验证码  (提示:点击验证码输入框,以获取验证码