汇编语言 访问CMOS RAM并打印时间(未完)

题目:以"年/月/日 时:分:秒"的格式,显示当前的日期,时间

提示:在此代码的基础上加以改造

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

方案1

assume cs:code
code segment
start:
  s: 
	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],7h ;为黑底白字
	mov es:[160*12+40*2+2],al
	mov byte ptr es:[160*12+40*2+3],7h ;为黑底白字
	
    mov byte ptr es:[160*12+40*2+4],2fh ;ASCII码对应/
	mov byte ptr es:[160*12+40*2+5],7h ;为黑底白字
	
	;这行不需要写xor ax,ax,原因是下方指令执行时会覆盖掉旧值
    mov al,8	;月
	out 70h,al	;传入8号单元的地址
	in al,71h	;取8号单元的内容,高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+6],ah 
	mov byte ptr es:[160*12+40*2+7],7h ;为黑底白字
	mov es:[160*12+40*2+8],al
	mov byte ptr es:[160*12+40*2+9],7h ;为黑底白字
	
	mov byte ptr es:[160*12+40*2+10],2fh ;ASCII码对应/
	mov byte ptr es:[160*12+40*2+11],7h ;为黑底白字
	
	mov al,7	;日
	out 70h,al	;传入7号单元的地址
	in al,71h	;取7号单元的内容,高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+12],ah 
	mov byte ptr es:[160*12+40*2+13],7h ;为黑底白字
	mov es:[160*12+40*2+14],al
	mov byte ptr es:[160*12+40*2+15],7h ;为黑底白字
	
	mov byte ptr es:[160*12+40*2+16],20h ;ASCII码对应空格
	mov byte ptr es:[160*12+40*2+17],7h ;为黑底白字
	
	mov al,4	;时
	out 70h,al	;传入4号单元的地址
	in al,71h	;取4号单元的内容,高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+18],ah 
	mov byte ptr es:[160*12+40*2+19],7h ;为黑底白字
	mov es:[160*12+40*2+20],al
	mov byte ptr es:[160*12+40*2+21],7h ;为黑底白字
	
	mov byte ptr es:[160*12+40*2+22],3Ah ;ASCII码对应:
	mov byte ptr es:[160*12+40*2+23],7h ;为黑底白字
	
	mov al,2	;分
	out 70h,al	;传入2号单元的地址
	in al,71h	;取2号单元的内容,高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+24],ah 
	mov byte ptr es:[160*12+40*2+25],7h ;为黑底白字
	mov es:[160*12+40*2+26],al
	mov byte ptr es:[160*12+40*2+27],7h ;为黑底白字
	
	mov byte ptr es:[160*12+40*2+28],3Ah ;ASCII码对应:
	mov byte ptr es:[160*12+40*2+29],7h ;为黑底白字
	
	mov al,0	;秒
	out 70h,al	;传入0号单元的地址
	in al,71h	;取0号单元的内容,高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+30],ah 
	mov byte ptr es:[160*12+40*2+31],7h ;为黑底白字
	mov es:[160*12+40*2+32],al
	mov byte ptr es:[160*12+40*2+33],7h ;为黑底白字
	jmp s ;无限条件1循环,一直刷新时间
	mov ax,4c00h
	int 21h
code ends
end start

最容易想到,虽然能成功显示,但是不够简洁,执行效率较低 

方案2

可以在方案1的基础上内嵌两个循环

CMOS RAM的存放单元为:

秒:0 分:2 时:4 日:7 月:8 年:9

0,2,4单元间隔2   7,8,9单元是连续的

注意:调用loop循环时必定会用到cx,但是在显示时间时用到了cx(mov cl,4),因此要入栈保存

assume cs:code
code segment
start:
s:
    xor si,si
	mov dl,9    ;从9号单元开始
	mov cx,3    ;循环3次  
    s1: 
	push cx     ;保存cx的值
	mov al,dl	;年
	out 70h,al	;传入al号单元的地址
	in al,71h	;取9号单元的内容,高4位为十位、低4位为个位
	mov ah,al
	mov cl,4             
	shr ah,cl			;高4位 
	and al,00001111b	;低4位
	add ah,30h  ;转换为十进制的ASCII码值
	add al,30h	;转换为十进制的ASCII码值
	mov bx,0b800h
	mov es,bx 
	mov es:[160*12+40*2+0+si],ah 
	mov byte ptr es:[160*12+40*2+1+si],7h ;为黑底白字
	mov es:[160*12+40*2+2+si],al
	mov byte ptr es:[160*12+40*2+3+si],7h ;为黑底白字
	
    mov byte ptr es:[160*12+40*2+4+si],2fh ;ASCII码对应/
	mov byte ptr es:[160*12+40*2+5+si],7h ;为黑底白字
	dec dl
	add si,6
	pop cx   ;恢复cx的值
	loop s1  ;年/月/日/打印的循环
	
	sub si,2
	;把日后面的/改成空格
	mov byte ptr es:[160*12+40*2+si],20h ;ASCII码对应空格
	add si,2 ;恢复si的值
	

    mov dl,4 ;从4号单元开始
	mov cx,3
    s2:
	push cx
	mov al,dl	
	out 70h,al	;传入al号单元的地址
	in al,71h	;取al号单元的内容,高4位为十位、低4位为个位
	mov ah,al
	mov cl,4
	shr ah,cl			;高4位 
	and al,00001111b	;低4位
	add ah,30h  ;转换为十进制的ASCII码值
	add al,30h	;转换为十进制的ASCII码值
	mov bx,0b800h
	mov es,bx 
	mov es:[160*12+40*2+18+0+si],ah 
	mov byte ptr es:[160*12+40*2+1+si],7h ;为黑底白字
	mov es:[160*12+40*2+2+si],al
	mov byte ptr es:[160*12+40*2+3+si],7h ;为黑底白字
	mov byte ptr es:[160*12+40*2+4+si],3Ah ;ASCII码对应:
	mov byte ptr es:[160*12+40*2+5+si],7h ;为黑底白字
	sub dl,2
	add si,6
	pop cx
	loop s2
	jmp s ;一直刷新时间
	
	mov ax,4c00h
	int 21h
code ends
end start

这是一个比较复杂的任务,需要在不同的硬件平台上使用不同的汇编语言来实现。以下是一个示例程序,使用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、付费专栏及课程。

余额充值