al总是获得零值,而不是计算程序运行的时间。我必须每5秒使用时钟单元的端口70和71打印一次。
.model small
.data
.code
msg db '@ $'
lastv db 0
saver db 0
start:
mov ax, @data
mov ds, ax
PollClock:
mov al, 00h ; set operation to count seconds
out 070h, al ; set operation to count seconds
in al, 071h ; any write to 0x70 should be followed by an action to 0x71 or the RTC will be left in an unknown state
mov saver, al
mov ah, 0h
mov bl, 5h
div bl
test ah, ah ;check if reminder is zero
jnz PollClock
mov al, saver
cmp lastv, al
jne PollClock
mov dx, offset msg
mov al, 0h
mov ah, 09h
int 21h
inc lastv
jmp PollClock
mov ah, 04ch
int 21h
end start
答案 0 :(得分:3)
对lastv
进行检查以防止在同一秒内多次循环是不正确的。
如果当前秒仍等于保存的最后一个,则应使用je PollClock
(请注意缺少的n
)返回循环。
此外,您不能正确处理lastv
:
0
(即分钟边界)上,这会使您的程序跳过第一个节拍。jne
条件),它将使您的程序每分钟打印一次,但随着该增加,它只会打印一次(当需要一分钟时),因为将来的迭代将要求秒必须是5的倍数且等于1。您应该:
lastv
变量初始化为一个不可能的值(例如5的非整数倍,或者仅仅是0ffh,超出几秒钟的范围)jne
转换为je
al
的值存储到lastv
中inc lastv
lastv db 0ffh ;Changed and moved
...
mov al, saver
cmp lastv, al
je PollClock ;Changed
mov lastv, al ;Added
...
;inc lastv ;Commented
但是在此之前,您需要将变量移到数据段中,否则通过ds
(隐式段寄存器)访问它们将无法为您提供正确的值。
这对于字符串msg
尤其重要。
额外
CMOS is a bit more involved than that的日期格式可以为二进制或BCD。
对于此应用程序,没关系。
还有一个正在进行的日期更新位,需要在读取完整日期时间之前进行检查。
同样,在这个简单的应用程序中(仅读取秒数)没关系。
最后,如果您打算尝试使用中断驱动的编程,则可以挂接int 1ch
(由IRQ0处理程序(int 08h
)调用),或在线使用CMOS周期性中断设置触发条件后,为IRQ8(int 70h
)。
还有一个等待服务(int 15h/ah=86h
),尽管由于DOS不是多任务的,所以通常没有用。