Subversion Repositories Kolibri OS

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
7638 leency 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