ASM System Time

Programming, for all ages and all languages.
Post Reply
Bobalandi
Member
Member
Posts: 107
Joined: Mon Dec 03, 2007 7:26 am
Location: Near Boston, MA
Contact:

ASM System Time

Post by Bobalandi »

Hey, it's my first time back here in a long time, but hopefully I'll be on more often. Anyways, is there an easy to get the time from the bios using intel assembly? Thanks in advance.
NULL
jzgriffin
Member
Member
Posts: 190
Joined: Tue Sep 26, 2006 1:40 pm
Libera.chat IRC: Nokurn
Location: Ontario, CA, USA
Contact:

Post by jzgriffin »

Read these indexes from the CMOS:

Code: Select all

Second = 0x00
Minute = 0x02
Hour = 0x04
Day = 0x07
Month = 0x08
Year = 0x09
Century = 0x32
Convert them from binary-coded decimal to binary and store them in variables.

Reading the CMOS:

Code: Select all

mov dx, 0x70
mov al, IDX
out dx, al
mov dx, 0x71
in al, dx
The BCD is now in AL.

Converting from BCD to binary: Sorry, you'll just have to translate this C macro, I'm in a hurry right now.

Code: Select all

#define BCD2BIN(val) (((val) & 0x0F) + ((val) >> 4) * 10)
p.s. Some of this code might be incorrect, as stated above, I'm in a rush.
Bobalandi
Member
Member
Posts: 107
Joined: Mon Dec 03, 2007 7:26 am
Location: Near Boston, MA
Contact:

Post by Bobalandi »

Thanks, I think that's what I needed.
NULL
Bobalandi
Member
Member
Posts: 107
Joined: Mon Dec 03, 2007 7:26 am
Location: Near Boston, MA
Contact:

Post by Bobalandi »

Sorry, but what is "IDX" in your example?
NULL
jzgriffin
Member
Member
Posts: 190
Joined: Tue Sep 26, 2006 1:40 pm
Libera.chat IRC: Nokurn
Location: Ontario, CA, USA
Contact:

Post by jzgriffin »

IDX stands for index--refer to the top of my previous post for a list related to your question.
Bobalandi
Member
Member
Posts: 107
Joined: Mon Dec 03, 2007 7:26 am
Location: Near Boston, MA
Contact:

Post by Bobalandi »

wait, so do am I supposed to define it.?
NULL
jzgriffin
Member
Member
Posts: 190
Joined: Tue Sep 26, 2006 1:40 pm
Libera.chat IRC: Nokurn
Location: Ontario, CA, USA
Contact:

Post by jzgriffin »

No, you replace IDX with the index you want to read. If you are using NASM you could convert the code I posted to a macro and use "macroname idx" then move AL into the corresponding variable for that index.
Bobalandi
Member
Member
Posts: 107
Joined: Mon Dec 03, 2007 7:26 am
Location: Near Boston, MA
Contact:

Post by Bobalandi »

So, I tried this code:

Code: Select all

_get_time:
	mov dx, 0x70
	mov al, 0x04
	out dx, al
	mov dx, 0x71
	in al, dx
	int 0x021
    ret
Which should return the hour, right? but nothing happened. :?
NULL
User avatar
Brendan
Member
Member
Posts: 8561
Joined: Sat Jan 15, 2005 12:00 am
Location: At his keyboard!
Contact:

Post by Brendan »

Hi,
Bobalandi wrote:

Code: Select all

_get_time:
	mov dx, 0x70
	mov al, 0x04
	out dx, al
	mov dx, 0x71
	in al, dx
	int 0x021
    ret
Which should return the hour, right? but nothing happened. :?
What is the int 0x21 there for?

Some more notes:
  • - It's theoretically possible for the RTC to be set to "binary" mode or "BCD mode", and also theoretically possible for the RTC to be set to "12-hour mode" or "24-hour mode". This means that at 11:00 in the afternoon the hour value may be 0x91 (BCD, 12-hour), 0x8B *binary, 12-hour), 0x23 (BCD, 24-hour) or 0x17 (Binary, 24-hour). Check CMOS register 0x0B to find out which mode the RTC is in.
    - You should have some sort of re-entrancy lock around this code, so that other code can't change the CMOS index before you read from the CMOS data.
    - All good OSs expect the RTC to be set to UTC. Unfortunately, badly designed OSs (Windows) expect the RTC to be set to Standard Time. This means you won't know which time the RTC is set to, and if the RTC is set to Standard Time you won't know if another OS has adjusted it for daylight savings or not (which is one of the reasons why good OSs use UTC).
Hope that helps...

Cheers,

Brendan
For all things; perfection is, and will always remain, impossible to achieve in practice. However; by striving for perfection we create things that are as perfect as practically possible. Let the pursuit of perfection be our guide.
User avatar
Dex
Member
Member
Posts: 1444
Joined: Fri Jan 27, 2006 12:00 am
Contact:

Post by Dex »

This will give you the time in realmode

Code: Select all

org 100h
segment .text
   mov ah,01h         ; from here to
   mov cx,2000h       ; ,,,,,,,,,,,,,
   int 10h            ; here, hide's cursor(bios int's)
m0:
   mov ah,2     ; get's the (bios int's)
   int 1ah      ; time in BCD , dl=0
   push cx
   push dx
   pop eax
m1:
   mov al,163
   sub dl,160   ; gives c,c,nc,c,c,nc,c,nc+z
   ja $+3      ;       h h :  m m  : s  s
   rol eax,4    ; if jump is taken, we're in the middle of this.

   push  ax
   mov ah,0eh
   int 10h

   pop  ax

   jne m1
   mov al,13   ; CR to re-position cursor - looks crappy.
   mov ah,0eh
   int 10h

 ;  mov ah,1     ; until key is pressed
 ;  int 16h
 ;  jz m0

   mov ah,01h         ; here to
   mov cx,0d0eh       ; ,,,,,,,,
   int 10h            ; here show cursor (bios int's)
   ret
The above code is coded with nasm.

Here is some code from DexOS, that has the full time/date functions written in fasm, but you will need to add your own print char function etc.

Code: Select all

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;                                                                                  ;;
;; Project          :   DexOS                                                       ;;
;; Ver              :   00.01                                                       ;;
;; Author           :   Dex                                                         ;;
;; Website          :   www.dex4u.com                                               ;;
;; Forum            :   http://jas2o.forthworks.com/dexforum/                       ;;
;; wiki             :   http://tonymac.asmhackers.net/Wiki/pmwiki.php               ;;
;; Date             :   October 31, 2006                                            ;;
;; Filename         :   TimeDate.inc                                                ;;
;; Assembler Command:   **********                                                  ;;
;; Copy Right Owners:   Team DexOS (c)2002-2007                                     ;;
;;                                                                                  ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;                                                                                  ;;
;; Team DexOS       :   0x4e71, bubach, crc, Dex, hidnplayr, jas2o, Solidus         ;;
;;                  :   smiddy, tony(mac), roboman, viki.                            ;;
;;                                                                                  ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;                                                                                  ;;
;; Disclaimer       :                                                               ;;
;; This software is provided "AS IS" without warranty of any kind, either           ;;
;; expressed or implied, including, but not limited to, the implied                 ;;
;; warranties of merchantability and fitness for a particular purpose. The          ;;
;; entire risk as to the quality and performance of this software is with           ;;
;; you.                                                                             ;;
;; In no event will the author's, distributor or any other party be liable to       ;;
;; you for damages, including any general, special, incidental or                   ;;
;; consequential damages arising out of the use, misuse or inability to use         ;;
;; this software (including but not limited to loss of data or losses               ;;
;; sustained by you or third parties or a failure of this software to operate       ;;
;; with any other software), even if such party has been advised of the             ;;
;; possibility of such damages.                                                     ;;
;;                                                                                  ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

 ;----------------------------------------------------;
 ; date                   ; fills vals with bcd date  ;
 ;----------------------------------------------------;
 ;                                                    ;
 ;   Input:                                           ;
 ;          none.                                     ;
 ;  Output:                                           ;
 ;          Puts bcd date in vals:                    ;
 ;          century, year, month, day.                ;
 ;                                             (100%) ;
 ;....................................................;

date:
	push  ds es
	pusha
	cli
	mov   al,32h					 ; RTC 32h
	out   70h,al
	in    al,71h					 ; read century
	mov   [century],al
	mov   al,9					 ; RTC 09h
	out   70h,al
	in    al,71h					 ; read year
	mov   [year],al
	mov   al,8					 ; RTC 08h
	out   70h,al
	in    al,71h					 ; read month
	mov   [month],al
	mov   al,7					 ; RTC 07h
	out   70h,al
	in    al,71h					 ; read day
	mov   [day],al
	sti
	popa
	pop   es ds

	ret

;====================================================;
; FloppyDate.                                        ;
;====================================================;
FloppyDate:
	pushad
	push  es
	push  ds
	mov   ax,18h
	mov   ds,ax
	mov   es,ax
	call  date
	xor   bx,bx
	mov   dx,bx
	mov   ax,bx
	mov   al,[year]
	call  Bcd2Bin
	add   al,20
	mov   dx,ax
	shl   dx,4
	mov   al,[month]
	call  Bcd2Bin
	and   al,00001111b
	add   dl,al
	shl   dx,5
	mov   al,[day]
	call  Bcd2Bin
	and   ax,0000000000011111b
	add   dx,ax
	mov   [FddDate],dx
	pop   ds
	pop   es
	popad
	ret

;====================================================;
; FloppyTime.                                        ;
;====================================================;
FloppyTime:
	pushad
	push  es
	push  ds
	mov   ax,18h
	mov   ds,ax
	mov   es,ax
	call  time
	xor   bx,bx
	mov   dx,bx
	mov   ax,bx
	mov   al,[hour]
	call  Bcd2Bin
	mov   dx,ax
	shl   dx,6
	mov   al,[minute]
	call  Bcd2Bin
	and   al,00111111b
	add   dl,al
	shl   dx,5
	mov   al,[second]
	shr   al,1
	call  Bcd2Bin
	and   ax,0000000000011111b
	add   dx,ax
	mov   [FddTime],dx 
	pop   ds
	pop   es
	popad
	ret

 ;----------------------------------------------------;
 ; prints date        ; prints the date in text mode  ;
 ;----------------------------------------------------;
 ;                                                    ;
 ;   Input:                                           ;
 ;          none.                                     ;
 ;  Output:                                           ;
 ;          prints the date in text mode.             ;
 ;                                             (100%) ;
 ;....................................................;

print_date:
	push  es
	pusha
	mov   esi,date_lable
	call  print_string
	call  date
	mov   al,[day]
	call  bcd_to_ASCII
	mov   bx,[val]
	mov   al,bl
	call  print_char
	mov   al,bh
	call  print_char

	mov   al,":"
	call  print_char

	mov   al,[month]
	call  bcd_to_ASCII
	mov   bx,[val]
	mov   al,bl
	call  print_char
	mov   al,bh
	call  print_char

	mov   al,":"
	call  print_char

	mov   al,[century]
	call  bcd_to_ASCII
	mov   bx,[val]
	mov   al,bl
	call  print_char
	mov   al,bh
	call  print_char
	mov   al,[year]
	call  bcd_to_ASCII
	mov   bx,[val]
	mov   al,bl
	call  print_char
	mov   al,bh
	call  print_char
	popa
	pop   es
	ret


 ;----------------------------------------------------;
 ; time                  ; fills vals with bcd time   ;
 ;----------------------------------------------------;
 ;                                                    ;
 ;   Input:                                           ;
 ;          none.                                     ;
 ;  Output:                                           ;
 ;          Puts bcd time in vals:                    ;
 ;          hour, minute, second.                     ;
 ;                                             (100%) ;
 ;....................................................; 
time:
	push  ds es
	pusha
	cli
	mov   al,4					 ; RTC  04h
	out   70h,al
	in    al,71h					 ; read hour
	mov   [hour],al
	mov   al,2					 ; RTC  02h
	out   70h,al
	in    al,71h					 ; read minute
	mov   [minute],al
	xor   al,al					 ; RTC  00h
	out   70h,al
	in    al,71h					 ; read second
	mov   [second],al
	sti
	popa
	pop   es ds

	ret

 ;----------------------------------------------------;
 ; prints time        ; prints the time in text mode  ;
 ;----------------------------------------------------;
 ;                                                    ;
 ;   Input:                                           ;
 ;          none.                                     ;
 ;  Output:                                           ;
 ;          prints the time in text mode.             ;
 ;                                             (100%) ;
 ;....................................................;

print_time:
	push  es
	pusha
	mov   esi,time_lable
	call  print_string
	call  time
	mov   al,[hour]
	call  bcd_to_ASCII
	mov   bx,[val]
	mov   al,bl
	call  print_char
	mov   al,bh
	call  print_char
       
	mov   al,":"
	call  print_char

	mov   al,[minute]
	call  bcd_to_ASCII
	mov   bx,[val]
	mov   al,bl
	call  print_char
	mov   al,bh
	call  print_char

	mov   al,":"
	call  print_char
   
	mov   al,[second]
	call  bcd_to_ASCII
	mov   bx,[val]
	mov   al,bl
	call  print_char
	mov   al,bh
	call  print_char
	popa
	pop   es
	ret

 ;----------------------------------------------------;
 ; set time                    ; set's time from vals ;
 ;----------------------------------------------------;
 ;                                                    ;
 ;   Input:                                           ;
 ;         Bcd time in vals.                          ;
 ;  Output:                                           ;
 ;         Prints ERROR msg on error.                 ;
 ;                                              (70%) ;
 ;....................................................;
set_time:					
	push  ds es
	pusha
	cli
	mov   bl,59h
	mov   al,[second]
	call  check_bcd_time				 ; check second number
	mov   al,[minute]
	call  check_bcd_time				 ; check minute number
	mov   bl,23h
	mov   al,[hour]
	call  check_bcd_time				 ; check hour number
	xor   al,al					 ; RTC 00h
	out   70h,al
	mov   al,[second]
	out   71h,al					 ; write second
	mov   al,2					 ; RTC 02h
	out   70h,al
	mov   al,[minute]
	out   71h,al					 ; write minute
	mov   al,4					 ; RTC 04h
	out   70h,al
	mov   al,[hour]
	out   71h,al					 ; write hour
	jmp   leave1
time_error:
	mov   esi,time_error_msg
	call  print_string
leave1:
	sti
	popa
	pop   es ds

	ret

 ;----------------------------------------------------;
 ; set date                    ; set's date from vals ;
 ;----------------------------------------------------;
 ;                                                    ;
 ;   Input:                                           ;
 ;         Bcd date in vals.                          ;
 ;  Output:                                           ;
 ;         Prints ERROR msg on error.                 ;
 ;                                              (70%) ;
 ;....................................................;         
set_date:
	push  ds es
	pusha
	cli
	mov   al,[day]
	mov   bl,31h
	or    al,al					 ; day cannot be 0
	jz    date_error
	call  check_bcd_date				 ; check day number
	mov   bl,12h
	mov   al,[month]
	or    al,al					 ; month cannot be 0
	jz    date_error
	call  check_bcd_date				 ; check month number
	mov   bl,99h
	mov   al,[year]
	call  check_bcd_date				 ; check year number
	mov   al,[century]
	call  check_bcd_date				 ; check century number
	mov   al,7					 ; RTC 07h
	out   70h,al
	mov   al,[day]
	out   71h,al					 ; write day
	mov   al,8					 ; RTC 08h
	out   70h,al
	mov   al,[month]
	out   71h,al					 ; write month
	mov   al,9					 ; RTC 09h
	out   70h,al
	mov   al,[year]
	out   71h,al					 ; write year
	mov   al,32h					 ; RTC 32h
	out   70h,al
	mov   al,[century]
	out   71h,al					 ; write century
	jmp   leave2
date_error:
	mov   esi,date_error_msg
	call  print_string
leave2:
	sti
	popa
	pop   es ds

	ret

 ;----------------------------------------------------;
 ; bcd_to_ASCII         ;converts bcd number to ASCII ;
 ;----------------------------------------------------;
 ;                                                    ;
 ;   Input:                                           ;
 ;         Bcd number in al.                          ;
 ;  Output:                                           ;
 ;         ASCII number in val.                       ;
 ;                                             (100%) ;
 ;....................................................;

bcd_to_ASCII:
       pusha						;start of convert
       mov  ah,al					;copy AL to AH
       and  ax,0f00fh					;mask bits
       mov  cl,4					;CL=04 for shift
       shr  ah,cl					;shift right AH to get unpacked BCD
       or   ax, 3030h					;combine with 30 to get ASCII
       xchg ah,al					;swap for ASCII storage convention
       mov  [val],ax					;store the ASCII value in VAL
       popa

       ret

	
 ;----------------------------------------------------;
 ; checks it a bcd number date                        ;
 ;----------------------------------------------------;
	
check_bcd_date:
	cmp   al,bl
	ja    date_error
	and   al,0Fh
	cmp   al,9
	ja    date_error
	ret
 ;----------------------------------------------------;
 ; checks it a bcd number time                        ;
 ;----------------------------------------------------;

check_bcd_time:
	cmp   al,bl
	ja    time_error
	and   al,0Fh
	cmp   al,9
	ja    time_error
	ret

;====================================================;
; Bcd2Bin.                                           ;
;====================================================;
Bcd2Bin:
	push  bx
	mov   bl,0x0a
	mov   bh,al
	shr   al,4
	mul   bl
	and   bh,0x0f
	add   al,bh
	pop   bx
	ret

 ;----------------------------------------------------;
 ; Data.                                              ;
 ;----------------------------------------------------;
time_lable:	   db " Time ",0
date_lable:	   db " Date ",0

val:	   dw 0,0

hour:	   db 0
minute:    db 0
second:    db 0

century:   db 0
year:	   db 0
month:	   db 0
day:	   db 0
FddDate    dw 0
FddTime    dw 0

Post Reply