汇编实验14:访问CMOS RAM

本文介绍如何通过编程访问CMOSRAM,以BCD码形式读取并显示当前的日期和时间。通过循环结构和地址表,实现了从CMOSRAM中获取年、月、日、时、分、秒信息。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

汇编实验14:访问CMOS RAM

任务

编程,以“年/月/日 时:分:秒”的格式,显示当前的日期,时间。

预备知识

CMOS存储当前时间的信息:年、月、日、时、分、秒。这六个信息的长度均为1个字节,并且以BCD码的形式存放(什么是BCD码?这里就不科普了,自行百度,反正我也只是略懂),存放的单元如下表所示:

024789

那么怎么访问CMOS的端口呢?这就要用到inout指令。另外要注意的是,这两条指令只能用寄存器AX和AL发送和接收端口的数据。
也就是只能用in ax/al,端口号读入数据,只能用out 端口号,ax/al写数据,当然,这里的端口号既可以放在寄存器里,也可以凡在内存单元里,也可以是立即数,这无所谓。

CMOS芯片内部有两个端口,地址分别为70h与71h。

  • 70h为地址端口,存放要访问的CMOS单元地址
  • 71为数据端口,存放读写数据

要读取CMOS的2号单元,应该这么写

    mov     al,2
    out     70h,al     ;将2送入端口70h中
    in      al,71h      ;从端口71h读取2号单元的内容

要将“0”写入CMOS的2号单元,应该这么写

    mov     al,2
    out     70h,al      ;将2送入端口70h
    mov     al,0
    out     71h,al      ;从端口71h写入0放到2号单元

编程思路

有了前面知识的铺垫,编程就变得相当简单。

在数据段先定义好输出格式

 time db '00/00/00 00:00:00$'

后面为什么加了个$符号呢?那是为了调用dos中断,用int 21h的9号功能输出字符串(没错,我就是这么懒,不想自己造轮子)。
接下来要从CMOS中读取时间信息,并且存放到数据段中去了。
显然这里要用到循环结构,为了方便,我还要定义一个地址表,给出各个时间信息的存放单元

list    db 9,8,7,4,2,1
;分别为年、月、日、时、分、秒的单元地址

用寄存器DI指向time字符串,用寄存器SI指向list地址表。每次循环调整时,
只要inc siadd di,3即可。

循环的核心部分思路,王爽的书中已经给出详细代码,就不在赘述(好吧,我就是懒)。这里有一点要注意的是,由于循环体中用到了CX寄存器,因此使用loop指令要注意寄存器CX的保护。其次,对于时间信息来说(这里以年为例子),‘16’年中数字16中的十位数字“ 1 ”在存储单元低地址位置,而个位数字“ 6 ”在存储单元高地址位置,因此我在实现的过程中,将数字“1”的ascii码放在寄存器AL中,将数字“6”的ascii码放在寄存器AH中,然后将寄存器AX整体复制到time字符串中。当然中间将BCD码转换成ASCII码的实现,在王爽的书里已经有了,就不贴出来了。

代码实现

其实这次实验很简单,代码也简单明了,一看就懂,没必要写注释了(偷懒偷得理直气壮,笑)

assume      cs:code,ds:data,ss:stack

data        segment
    time    db  '00/00/00 00:00:00$'
    list    db  9,8,7,4,2,0     
data        ends

stack       segment
    db  256 dup(0)
stack       ends

code        segment

main:       mov     ax,data
            mov     ds,ax
            mov     ax,stack
            mov     ss,ax
            mov     sp,256


            mov     si,offset list
            mov     di,offset time
            mov     cx,6
    s:      push    cx
            mov     al,[si]
            out     70h,al
            in      al,71h

            mov     ah,al
            mov     cl,4
            shr     al,cl
            and     ah,00001111b
            add     ax,3030h

            mov     [di],ax

            add     di,3
            inc     si
            pop     cx
            loop    s

            mov     ah,9
            mov     dx,offset time
            int     21h         

            mov     ax,4c00h
            int     21h

code        ends

end     main

最后的效果是这样的:

这里写图片描述

总结

这篇博文本来我早就想发的,但是因为种种原因,拖到现在才发(我发誓,这次真的不是因为懒)。王爽的《汇编语言(第三版)》马上就要读完了,感觉自己慢慢开始入门了,找到了点汇编的门道,虽然前面的路还很长(32位汇编,实模式,保护模式,AT&T,inte,IA32,以上名词本人一无所知),但我还是有信心可以成为“牛人”的。读完这本书以后,我就要开始数据结构和算法的学习了,业余时间我还想读一读《深入理解计算机系统》(CSAPP),我听说学校有一门课的教材就是这本书,这老师是要把学生培养成“牛人”,然后上天的节奏啊!!!不过这个过程还是很幸苦的。(只要你成为牛人,那么即使成为书呆子也无所谓啦

转载于:https://www.cnblogs.com/wyf12138/p/6581525.html

这是一个比较复杂的任务,需要在不同的硬件平台上使用不同的汇编语言来实现。以下是一个示例程序,使用8086汇编语言,在IBM PC上显示时间: ``` ; 设置DS为0,将数据段指向0段 MOV AX, 0 MOV DS, AX ; 设置CMOS RAM端口 MOV AL, 0x70 OUT 0x70, AL ; 读取年份 MOV AL, 0x09 OUT 0x71, AL IN AL, 0x71 MOV BL, AL ; 读取月份 MOV AL, 0x08 OUT 0x71, AL IN AL, 0x71 MOV CL, AL ; 读取日期 MOV AL, 0x07 OUT 0x71, AL IN AL, 0x71 MOV DL, AL ; 读取小时 MOV AL, 0x04 OUT 0x71, AL IN AL, 0x71 MOV DH, AL ; 读取分钟 MOV AL, 0x02 OUT 0x71, AL IN AL, 0x71 MOV AH, AL ; 读取秒钟 MOV AL, 0x00 OUT 0x71, AL IN AL, 0x71 MOV BH, AL ; 计算星期 MOV AL, DL MOV BL, CL MOV CL, 0 MOV DL, 4 DIV DL ADD AL, 2 MOV DL, 7 DIV DL ; 显示时间 MOV AH, 0x0E MOV BH, 0 MOV BL, 0x07 ; 显示年份 MOV AL, BL MOV BL, BH MOV BH, 0 MOV CX, 4 CALL DISPLAY_HEX MOV AL, BL MOV BH, 0 CALL DISPLAY_HEX ; 显示月份 MOV AL, CL MOV BH, 0 CALL DISPLAY_HEX ; 显示日期 MOV AL, DL MOV BH, 0 CALL DISPLAY_HEX ; 显示小时 MOV AL, DH MOV BH, 0 CALL DISPLAY_HEX ; 显示分钟 MOV AL, AH MOV BH, 0 CALL DISPLAY_HEX ; 显示秒钟 MOV AL, BH MOV BH, 0 CALL DISPLAY_HEX ; 显示星期 MOV AH, 0x0E MOV AL, 0x20 INT 0x10 MOV AL, 0x20 INT 0x10 MOV AL, 0x20 INT 0x10 MOV AL, 0x20 INT 0x10 MOV AL, 0x20 INT 0x10 MOV AL, 0x20 INT 0x10 MOV AL, 0x20 INT 0x10 MOV AL, 0x31 ADD AL, DL MOV BH, 0 MOV BL, 0x07 INT 0x10 ; 退出程序 MOV AH, 0x4C INT 0x21 ; 显示十六进制数 DISPLAY_HEX: PUSH AX PUSH BX PUSH CX MOV CX, 4 DISPLAY_HEX_LOOP: ROL AL, 4 MOV BL, AL AND BL, 0x0F CMP BL, 0x0A JL DISPLAY_HEX_CHAR ADD BL, 0x37 JMP DISPLAY_HEX_OUTPUT DISPLAY_HEX_CHAR: ADD BL, 0x30 DISPLAY_HEX_OUTPUT: MOV AH, 0x0E INT 0x10 LOOP DISPLAY_HEX_LOOP POP CX POP BX POP AX RET ``` 注意,这段代码可能需要根据实际情况进行调整,如CMOS RAM端口的地址可能示例代码不同。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值