为什么 AL 每次都得到零值?

Why is AL gets the value zero each time?

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

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

如果当前秒数仍等于上次保存的秒数,则应使用 je PollClock(注意缺少的 n)返回循环。
此外,您没有正确处理 lastv

  • 你用 0 初始化它,它是 5 的有效倍数。这将使你的程序跳过第一个节拍,如果它恰好在第二个 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。
对于这个应用程序,它并不重要。

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

最后,如果您有心情尝试 interrupt-driven 编程,您可以在编程触发条件后挂钩 int 1ch, which is called by the IRQ0 handler (int 08h), or use the CMOS periodic interrupt on line IRQ8 (int 70h)。

还有一个等待服务 (int 15h/ah=86h) 虽然这通常没有用,因为 DOS 不是 multi-tasked。