;*****************************************************************************
; EPOCH.ASM  
; (c) 2012 Erdogan TAN  [ 14/07/2012 ]  Last Update: 14/07/2012
;
; This program shows UNIX EPOCH/TIME (seconds) for current date and time 
;

Present segment Para 'code'

		assume CS:Present, DS:Present, ES:Present, SS:Present


;±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
;±
;±              PROCEDURE main
;±
;±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±

main    proc    far

        org 100h
start:
	mov si, offset msg_program_info
	call print_string

     	call epoch

	push ax
	mov ax, dx
	call proc_hex_double
	mov word ptr [unix_time], dx
	mov word ptr [unix_time]+2, ax
	pop ax
	call proc_hex_double
	mov word ptr [unix_time]+4, dx
	mov word ptr [unix_time]+6, ax

	mov si, offset msg_current_datetime
	call print_string

	mov si,offset msg_unix_time
	call print_string				

	int 20h

main    endp

print_string    proc near

            	mov 	bx, 07h  
                mov     ah, 0Eh   

print_string_loop:
                lodsb                           ; Load byte at DS:SI to AL
                and     al, al       
                jz      short print_string_ok      
       
                int     10h                     ; BIOS Service func ( ah ) = 0Eh
                                                ; Write char as TTY
                                                ;AL-char BH-page BL-color
                jmp     short print_string_loop           

print_string_ok:
                retn

print_string    endp

;'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''';
; From binary (word) to hexadecimal (character) converter    ;
;                                                            ;
; input -> AX = word (binary number) to be converted         ;
; output -> DX = First 2 characters of hexadecimal number    ;
; output -> AX = Last 2 characters of hexadecimal number     ;
;                                                            ;
; (c) Erdogan Tan  [ 28/1/2002 ]                             ;
;............................................................;

proc_hex_double  proc    near

	push cx
        xor dx, dx
        mov cx, 10h
        div cx      ; Q in AX, R in DX (DL)
        xchg dh, dl ; DH= 0, R in DL <- CX= 10h 
        push dx     ; R in DH, DL= 0
        xor dh, dh
        div cx
        push dx     ; R in DL, DH= 0, AX <= FFh
        div cl      ; AX <= 0Fh
       	            ; R in AH, Q in AL, AL (Q) is 0
        push ax
        pop dx      ; High Word Characters is in DX
	pop cx      ; R in CL
        pop ax      ; R in AH, AL = 0
        or al, cl
                 
        or dx,'00'

        cmp dl,'9'
        jna short pass_cc_dl
        add dl,7
pass_cc_dl:
        cmp dh,'9'
        jna short pass_cc_dh
        add dh,7
pass_cc_dh:
        or ax, '00'

        cmp al,'9'
        jna short pass_cc_al
        add al,7
pass_cc_al:
        cmp ah,'9'
        jna short pass_cc_ah
        add ah,7
pass_cc_ah:
        pop cx

        retn

proc_hex_double  endp


;'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''';
; 32 bit Multiply                                            ;
;- - - - - - - - - - - - - - - - - - - - - - - - - -- - - - -;
;                                                            ;
; input -> DX_AX = 32 bit multiplier                         ;
; input -> BX = 16 bit number to be multiplied by DX_AX      ;
; output -> BX_DX_AX = 48 bit (16+32 bit) result number      ;
;                                                            ;
; (c) Erdogan TAN  1999                                      ;
;............................................................;

proc_mul32 proc near

    ; push cx

      mov cx, bx
      mov bx, dx

      mul cx

      xchg ax, bx

      push dx

      mul cx 

      pop cx 

      add ax, cx 
      adc dx, 0

      xchg bx, ax
      xchg dx, bx

    ; pop cx

      retn

proc_mul32 endp

epoch proc near
	; 14/7/2012		
	; Erdogan Tan - RETRO UNIX v0.1
	; compute current date and time as UNIX Epoch/Time
	; UNIX Epoch: seconds since 1/1/1970 00:00:00

	mov ah, 02h                      ; Return Current Time
        int 1Ah
        xchg ch,cl
        mov word ptr [hour], cx
        xchg dh,dl
        mov word ptr [second], dx

        mov ah, 04h                      ; Return Current Date
        int 1Ah
        xchg ch,cl
        mov word ptr [year], cx
        xchg dh,dl
        mov word ptr [month], dx

	mov cx, 3030h

	
	mov al, byte ptr [hour] ; Hour
           ; AL <= BCD number)
        db 0D4h,10h                     ; Undocumented inst. AAM
					; AH = AL / 10h
					; AL = AL MOD 10h
	mov dx, ax
	xchg dh, dl
	add dx, 3030h
	mov word ptr [str_Hour], dx

        aad ; AX= AH*10+AL
		
	mov byte ptr [hour], al

	mov al, byte ptr [hour]+1 ; Minute
           ; AL <= BCD number)
        db 0D4h,10h                     ; Undocumented inst. AAM
					; AH = AL / 10h
					; AL = AL MOD 10h
	mov dx, ax
	xchg dh, dl
	add dx, cx
	mov word ptr [str_Minute], dx

        aad ; AX= AH*10+AL
		
	mov byte ptr [minute], al

	mov al, byte ptr [second] ; Second
           ; AL <= BCD number)
        db 0D4h,10h                     ; Undocumented inst. AAM
					; AH = AL / 10h
					; AL = AL MOD 10h
	mov dx, ax
	xchg dh, dl
	add dx, cx
	mov word ptr [str_Second], dx

        aad ; AX= AH*10+AL
		
	mov byte ptr [second], al

	
	mov ax, word ptr [year] ; Year (century)
        push ax
	   ; AL <= BCD number)
        db 0D4h,10h                     ; Undocumented inst. AAM
					; AH = AL / 10h
					; AL = AL MOD 10h
	mov dx, ax
	xchg dh, dl
	add dx, cx
	mov word ptr [str_Year], dx

        aad ; AX= AH*10+AL
		
	mov ah, 100
	mul ah
	mov word ptr [year], ax

	pop	ax
	mov	al, ah
           ; AL <= BCD number)
        db 0D4h,10h                     ; Undocumented inst. AAM
					; AH = AL / 10h
					; AL = AL MOD 10h
	mov dx, ax
	xchg dh, dl
	add dx, cx
	mov word ptr [str_Year]+2, dx

        aad ; AX= AH*10+AL
		
	add word ptr [year], ax


	mov al, byte ptr [month] ; Month
           ; AL <= BCD number)
        db 0D4h,10h                     ; Undocumented inst. AAM
					; AH = AL / 10h
					; AL = AL MOD 10h
	mov dx, ax
	xchg dh, dl
	add dx, cx
	mov word ptr [str_Month], dx

        aad ; AX= AH*10+AL
	
	mov byte ptr [month], al	


	mov al, byte ptr [month]+1 ; Day
           ; AL <= BCD number)
        db 0D4h,10h                     ; Undocumented inst. AAM
					; AH = AL / 10h
					; AL = AL MOD 10h
	mov dx, ax
	xchg dh, dl
	add dx, cx
	mov word ptr [str_Day], dx

        aad ; AX= AH*10+AL

	mov byte ptr [Day], al
	
convert_to_epoch:

	mov dx, word ptr [year]
	sub dx, 1970
	mov ax, 365
	mul dx
	xor bh, bh
	mov bl, byte ptr [month]
	dec bl
	shl bl, 1
	mov cx, word ptr DMonth[BX]
	mov bl, byte ptr [Day]
	dec bl
	
	add ax, cx
	adc dx, 0
	add ax, bx
	adc dx, 0
				; DX:AX = days since 1/1/1970
	mov cx, word ptr [year]
	sub cx, 1969
	shr cx, 1
	shr cx, 1		
		; (year-1969)/4
	add ax, cx
	adc dx, 0
				; + leap days since 1/1/1970

	cmp byte ptr [month], 2  ; if past february
	jna short @f
	mov cx, word ptr [year]
	and cx, 3 ; year mod 4
	jnz short @f		
				; and if leap year
	add ax, 1 ; add this year's leap day (february 29)
	adc dx, 0
@@: 			; compute seconds since 1/1/1970
	mov bx, 24
	call proc_mul32

	mov bl, byte ptr [hour]
	add ax, bx
	adc dx, 0
	
	mov bx, 60
	call proc_mul32

	mov bl, byte ptr [minute]
	add ax, bx
	adc dx, 0
	
	mov bx, 60
	call proc_mul32

	mov bl, byte ptr [second]
	add ax, bx
 	adc dx, 0

	; DX:AX -> seconds since 1/1/1970 00:00:00
	
	retn

epoch endp

year: dw 1970
month: dw 1
day: dw 1
hour: dw 0
minute: dw 0
second: dw 0

DMonth:
dw 0
dw 31
dw 59
dw 90
dw 120
dw 151
dw 181
dw 212
dw 243
dw 273
dw 304
dw 334
; dw 365

db 0

msg_program_info:
        db "UNIX Epoch/Time program by Erdogan Tan [14/7/2012]"
	db  0dh, 0Ah, 0Dh, 0Ah, 0

msg_current_datetime:
	db "Current Date&Time is "
str_Day:
        dw 3030h
	db "/"
str_Month:
        dw 3030h
	db "/"
str_Year:
	dd 30303030h
	db " "
str_Hour:
	dw 3030h
	db ":"
str_Minute:
	dw 3030h
	db ":"
str_Second:
	dw 3030h
	db 0Dh, 0Ah, 0

msg_unix_time:
	db "Current Unix Time is "
unix_time:
	dd 30303030h
	dd 30303030h
	db "h"

	db 0Dh, 0Ah, 0

Present ends

        end start
