Tomer Gross
Tomer Gross

Reputation: 15

Why is AL gets the value zero each time?

al is always getting the value zero instead of counting the time the program running. I have to print @ every 5 seconds by using ports 70 & 71 of the clock unit.

.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

Upvotes: 0

Views: 67

Answers (1)

Margaret Bloom
Margaret Bloom

Reputation: 44058

The check on lastv to prevent looping on the same second multiple times is not correct.

It should use a je PollClock (note the missing n) to go back looping if the current second is still equal to the last one saved.
Furthermore you don't handle lastv correctly:

  • You initialise it with 0 which is a valid multiple of 5. This would make your program skip the first beat if it happens to be on second 0 (i.e. on a minute boundary).
  • You don't save it after the divisibility test. If you didn't increment it after the printing (keep the jne condition of above) it would make your program print every minute but with that increment it will only print once (when a minute is due) since future iterations will require the second to be both a multiple of 5 and equal to 1.

You should:

  • Initialise the lastv var with an impossible value (e.g. a non multiple of 5 or simply 0ffh which is out of range for seconds)
  • Convert the jne to je
  • Store the value of al into lastv before printing
  • Remove the inc lastv

 

lastv db 0ffh           ;Changed and moved

...

mov al, saver
cmp lastv, al
je PollClock            ;Changed

mov lastv, al           ;Added

...

;inc lastv              ;Commented

But before that you need to move the variables into the data segment otherwise accessing them through ds (the implicit segment register) won't give you the right values.
This is especially important for the string msg.


Extra

The CMOS is a bit more involved than that, the date format can either be binary or BCD.
For this application it doesn't matter though.

There is also a date update in progress bit which needs to be checked before reading the full date-time.
Again, in this simple application (where only the seconds are read) it doesn't matter.

Finally, if you are in the mood to experiment with interrupt-driven programming you can hook int 1ch, which is called by the IRQ0 handler (int 08h), or use the CMOS periodic interrupt on line IRQ8 (int 70h) after programming the trigger conditions.

There is also a wait service (int 15h/ah=86h) though this is usually not useful as DOS is not multi-tasked.

Upvotes: 3

Related Questions