; delay.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)
; utilizaremos os registradores eax e ebx do 386+ para guardar os
; valores  inicial e final do contador que devem diferir de 18*n
; (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 [timein],eax    ; save initial counter
    mov [timefin],ebx   ; save final counter
    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)
    xor eax, eax   ; clear eax
    mov ax, cx
    mov dx,18
    mul dx         ;ax= no of ticks to delay
    push ds        ;save ds on stack
    xor cx,cx
    mov ds, cx     ; segment zero
    mov ebx, [046ch] ; get RTC counter
    push ebx
    add eax, ebx         ; get target value in eax
L0:
    mov ebx, [0x046c] ; get RTC 32 bit counter
    cmp ebx, eax      ; if less than target
    jb  L0            ; loop back
    pop eax           ; get initial counter
    pop cx            ; get data segment
    mov ds,cx           ; restore it
    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
