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

时间:2019-06-11 08:03:29

标签: assembly dos x86-16

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

1 个答案:

答案 0 :(得分:3)

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。
对于此应用程序,没关系。

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

最后,如果您打算尝试使用中断驱动的编程,则可以挂接int 1ch(由IRQ0处理程序(int 08h)调用),或在线使用CMOS周期性中断设置触发条件后,为IRQ8(int 70h)。

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