Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | Download | RSS feed

  1. ;
  2. ;  SNTP library
  3. ;
  4. ;  (C) 2019 Coldy      
  5. ;  Thank's you for use this code and software based on it!
  6. ;  I will glad if it's will be helpful.
  7. ;
  8. ;  Distributed under terms of GPL
  9. ;
  10.  
  11. ; Inline clearing register(s)
  12. ; E.g. uses:
  13. ; clear eax      ; - clearing single register
  14. ; or
  15. ; clear eax, ebx ; ... and so on - clearing multiple register
  16. macro clear [reg]  { xor reg, reg }
  17.  
  18. macro b2bcd
  19. ;   Convert hex byte to BCD byte
  20. ;   Input:
  21. ;   al = number 0...99 (not checking)
  22. ;   Output:
  23. ;   al = number in BCD
  24. ;   Algorithm:
  25. ;   al = (al > 9) ? ((al / 10) * 6 + al) : al
  26. ;   Use registers (not restore):
  27. ;   eax, ebx, edx
  28. {
  29.     clear ebx, edx
  30.     cmp al, 9         ; (al <= 9 ?)  
  31.     jle @f
  32.     mov bl, al
  33.     mov dl, 10
  34.     div dl            ; al = al/10
  35.     mov dl, 6
  36.     mul dl            ; al = al*6
  37.     add al, bl        ; al = al + bl
  38. @@:
  39. }
  40.  
  41. struct DateTime
  42.   struct
  43.     day   db ?
  44.     month db ?
  45.     year  dw ?
  46.   ends
  47.   struct
  48.     hour  db ?
  49.     min   db ?
  50.     sec   db ?
  51.   ends
  52. ends
  53.  
  54.  
  55. proc DateTime2bcd
  56.    ;
  57.    ;  Input:
  58.    ;  eax => pointer to DateTime (UNIX time since 1.1.1970 00:00:00 GMT )
  59.    ;
  60.    ; Output:
  61.    ; eax  => time in ÂÑD format
  62.    ; edx  => date in BCD format
  63. locals
  64.   date dd 0
  65.   time dd 0
  66. endl
  67.  
  68.   mov esi, eax
  69.   clear eax, ebx, ecx
  70.   mov al, [esi + DateTime.day]
  71.   cmp al, 9
  72.   jle @f
  73.   mov bl, al
  74.   mov cl, 10
  75.   div cl
  76.   mul bl, cl
  77.   add al, bl
  78. @@:
  79. endp
  80.  
  81.  
  82.  
  83. YEAR_EPOCH            = 1970
  84. YEAR_FIRST_LEAP_YEAR  = 1972
  85. SEC_IN_MINUTE         = 60
  86. SEC_IN_HOUR           = (SEC_IN_MINUTE * 60)
  87. SEC_IN_DAY            = (SEC_IN_HOUR * 24)
  88. SEC_IN_YEAR           = (SEC_IN_DAY * 365)
  89.  
  90. proc timestamp2DateTime
  91.    ;
  92.    ;  Input:
  93.    ;  eax => timestamp (UNIX time since 1.1.1970 00:00:00 GMT )
  94.    ;  ebx => pointer to DateTime
  95.    ;
  96.    ; Output:
  97.    ; none
  98.    ;
  99.    ; Use registers (not restore):
  100.    ;
  101.    ; History:
  102.    ; 14.04.2019 Bug fixed: Incorrect output day (-1 day error)!!!
  103.    ; 19.04.2019 Bug fixed: Incorrect convert of time with maximum UNIX time (0x7ffffff)
  104.    ;
  105.    ; Known isuues:
  106.    ;  Not yet seen :)
  107.    ;
  108. locals
  109.   timestamp  dd ?
  110.   years      dw ?
  111.   lyears     dw ?
  112.   ;year       dw ?
  113.   ;_ts        dd 0
  114.   ;ts         dd 0
  115.   MonthDays  db 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
  116.   ;month      db ?
  117. endl
  118.      
  119.   ;pusha
  120.   mov  [timestamp], eax
  121.   mov  esi, ebx ; ESI => pointer to DateTime
  122.    
  123.   ; Calculate total years since year epoch
  124.   cdq
  125.   mov     ebx, SEC_IN_YEAR + SEC_IN_DAY/4
  126.   idiv  ebx
  127.   mov [years], ax ; (AX => years)
  128.  
  129.   ; Calculate current year
  130.   add ax, YEAR_EPOCH
  131.   mov [esi + DateTime.year], ax ; (AX => year)
  132.  
  133.   ; Calculate leap years since year epoch
  134.   ;xor   ecx, ecx ; Clear
  135.   ;mov   cx, bx
  136.  
  137.   ;Fix: -1 day error
  138.   dec   ax
  139.   sub   ax, YEAR_FIRST_LEAP_YEAR ; - 1
  140.  
  141.   clear   ebx, edx
  142.   mov   bx, 4
  143.   idiv  bx
  144.   cmp     [esi + DateTime.year], YEAR_FIRST_LEAP_YEAR + 1
  145.   js    @f
  146.   inc   al
  147. @@:
  148.   mov [lyears], ax
  149.  
  150.   ; Drop years seconds
  151.   mov   eax, [timestamp]
  152.   clear   ebx
  153.   mov   bx, [years]
  154.   sub   bx, [lyears]
  155.   mov   ecx, SEC_IN_YEAR
  156.   imul  ebx, ecx                  ; ebx => (years - lyears) * SEC_IN_YEAR
  157.   clear   ecx
  158.   mov   cx, [lyears]
  159.   mov   edx, SEC_IN_YEAR + SEC_IN_DAY
  160.   imul  ecx, edx                  ; cx => lyears * (SEC_IN_YEAR + SEC_IN_DAY)
  161.   add   ebx, ecx                  ; bx => (years - lyears) * SEC_IN_YEAR + lyears * (SEC_IN_YEAR + SEC_IN_DAY)
  162.   sub   eax, ebx                
  163.   mov   [timestamp], eax
  164.  
  165.   ;Is leap year?
  166.   clear ecx, edx
  167.   mov   cx, [esi + DateTime.year]
  168.   mov   eax, ecx
  169.   mov   ebx, 4
  170.   div   bx
  171.   cmp   dx, 0
  172.   je   leap
  173.   mov   ax, cx
  174.   mov  bx, 100
  175.   div  bx
  176.   cmp   dx, 0
  177.   je   leap
  178.   mov   ax, cx
  179.   mov  bx, 400
  180.   clear dx
  181.   div  bx
  182.   cmp   dx, 0
  183.   jmp   @f    
  184. leap:
  185.   ; Add +1 day in february if leap year
  186.   inc [MonthDays + 1]
  187. @@:  
  188.  
  189.   ; Calculate current month
  190.   clear  eax, ecx, edi       ; _ts, ts, month (Bug? => ecx != 0)
  191. caclmonth:
  192.   clear  ebx
  193.   mov  bl, [MonthDays + edi]
  194.   imul ebx, SEC_IN_DAY
  195.   inc  edi
  196.   add  eax, ebx
  197.  
  198.   ; {{ 19.4.2019 Bug was somewhere here
  199.   cmp edi, 12
  200.   je    @f
  201.   ; TODO: if edi >= 12 then error!
  202.   ;mov eax, -1
  203.   ;mov edx, 0
  204.   ;ret
  205. ;@@:
  206.   cmp eax, [timestamp]
  207.   jge    @f            ; Bug? => jg    @f
  208.   mov  ecx, eax
  209.   jmp  caclmonth
  210.   ; }}
  211. @@:
  212.   ; Drop months seconds
  213.   sub [timestamp], ecx
  214.   mov eax, edi
  215.   mov [esi + DateTime.month], al
  216.  
  217.   ; Calculate elapsed day
  218.   mov   eax, [timestamp]
  219.   clear   edx
  220.   mov   ebx, SEC_IN_DAY
  221.   idiv  ebx     ; eax => day
  222.  
  223.   ; Drop days seconds
  224.   imul  ebx, eax, SEC_IN_DAY
  225.   sub   [timestamp],ebx
  226.  
  227.   ; Correct current day
  228.   add   eax, 1  ; eax => current day
  229.   mov [esi + DateTime.day], al
  230.  
  231.   ; Calculate current hour
  232.   mov   eax, [timestamp]
  233.   clear   edx
  234.   mov   ebx, SEC_IN_HOUR
  235.   idiv  ebx
  236.   mov [esi + DateTime.hour], al
  237.  
  238.   ; Drop hours seconds
  239.   imul ebx, eax, SEC_IN_HOUR
  240.   sub  [timestamp],ebx
  241.  
  242.   mov   eax, [timestamp]
  243.   clear   edx
  244.   mov   ebx, SEC_IN_MINUTE
  245.   idiv  ebx
  246.   mov [esi + DateTime.min], al
  247.  
  248.   ; Drop minutes seconds
  249.   imul ebx, eax, SEC_IN_MINUTE
  250.   sub  [timestamp],ebx
  251.   mov eax, [timestamp]
  252.   mov [esi + DateTime.sec], al
  253.          
  254.   ;popa
  255.   ret
  256. endp