首页 > 解决方案 > 为什么 AL 每次都取值为零?

问题描述

al 总是将值设为零,而不是计算程序运行的时间。我必须使用时钟单元的端口 70 和 71 每 5 秒打印一次 @。

.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

标签: assemblydosx86-16

解决方案


检查lastv以防止在同一秒上多次循环是不正确的。

如果当前秒仍然等于最后保存的秒,它应该使用je PollClock(注意缺少的n)返回循环。
此外,您没有lastv正确处理:

  • 你用 0 初始化它,它是 5 的有效倍数。如果它恰好在第二个0(即在分钟边界上),这将使你的程序跳过第一个节拍。
  • 可分性测试后您不保存它。如果您在打印后没有增加它(保持上述jne条件),它将使您的程序每分钟打印一次,但随着该增量,它只会打印一次(当一分钟到期时),因为未来的迭代将需要第二个既是 5 的倍数又等于 1。

你应该:

  • 用一个不可能的值初始化lastvvar(例如,一个非 5 的倍数或简单的 0ffh,它在几秒钟内超出范围)
  • 转换jneje
  • 在打印之前存储alinto的值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 比这更复杂一些,日期格式可以是二进制或 BCD。
对于这个应用程序,它并不重要。

还有一个正在进行的日期更新位,在读取完整的日期时间之前需要检查它。
同样,在这个简单的应用程序(只读取秒数)中,这无关紧要。

最后,如果您有兴趣尝试中断驱动编程,您可以挂钩int 1ch,由 IRQ0 处理程序 () 调用,或者在编程触发条件后int 08h使用 IRQ8 () 线上的 CMOS 周期性中断。int 70h

还有一个等待服务(int 15h/ah=86h),尽管这通常没有用,因为 DOS 不是多任务的。


推荐阅读