; newdelay.asm                            Celio G.  29 Out 2001
; implementa uma rotina delay(n) que faz o programa esperar n segundos,
; via leitura do contador de 32 bits do RTC(Real Time Clock) do PC
; cujo tick=54.9 ms (~18 vezes por segundo) e atualizado pelo BIOS
; a partir da posicao de memoria 0000:046C
; (o contador e' zerado as 24 horas: seu valor maximo e' 0x1800AF)
; (n=8 neste teste; 18*n=144=0x90).
; Para poder ler o valor do contador devemos mudar o valor de ds para 0

org 100h
segment .text
    mov dx,init          ; shows initial message
    mov ah,9
    int 21h

    mov cx, 8           ; delays 8 secs
    ;cli                 ; disable interrupts!? should lock program, but
                        ; it only delays sending 1st message to video
    call delay          ;
    mov dx,msg          ; shows message Hello World!
    mov ah,9
    int 21h
    mov ah,4Ch
    int 21h
;*******************************************************************
; rotina para fazer um programa esperar n segundos
; le o valor do RTC atualizado pelo BIOS em 046ch;
; deve ser executada com interrupcoes ativadas
; entrada: cx = numero de segundos para esperar
; saida:  eax= valor inicial do contador do RTC (32 bits)
;         ebx= valor final do contador do RTC
;*******************************************************************

delay:             ; delay cx secs (cx < 3598 secs= ~1h)
    mov ax, cx
    mov dx,18
    mul dx         ;ax= no of ticks to delay
    mov cx,ax      ; save in cx
    call time
    add  cx,ax     ; no of ticks in the future
    adc  dx,0      ; add CY if needed
    mov  di, dx    ;  (di,cx)= future tick count (high, low)
dl0:
    call time
    cmp  di, dx
    ja dl0
    cmp cx, ax
    ja dl0         ; low part future > low part present, loop again
    ret
;********************************************************************
time:              ; return current time  (in ticks since midnight) setup by BIOS
                   ; output ax= no ticks low dx= no ticks high
    push ds
    pushf          ; want to save current interrupt flag
    xor ax,ax
    mov ds,ax
    mov ax, [46ch]  ; low part
    mov dx, [46eh]  ; high part
    popf
    pop ds
    ret

segment .data
init: db 'Esperando 8 segundos..',0dh,0ah,'$'
msg: db 'Hello, World!',0Dh,0Ah,'$'
savds: dw 0
timein:  dd 0
timefin: dd 0
