[feat] add option -n print next prayer 24-hour
[azan.git] / azan-nasm.s
blob44feaab06a4a79c9b2d115101aa2cef419cd73e2
1 ; See LICENSE file for copyright and license details.
2 ; azan-nasm is simple muslim prayers calculator.
3 ; print next prayer left duration or today's all prayers.
5 BITS 64
6 %include "syscalls.s"
7 %include "macros.s"
8 %include "math.s"
9 %include "config.s"
10 CHECK_OPENBSD
12 section .rodata
13 sec_inday: dq 0x40f5180000000000 ;double 86400.0
14 jul1970: dq 0x41429ec5c0000000 ;double 2440587.5
15 offset: dq 0xc142b42c80000000 ;double -2451545
16 to_rad: dq 0x3f91df46a2529d39 ;double pi / 180
17 to_deg: dq 0x404ca5dc1a63c1f8 ;double 180 / pi
18 g_1: dq 0x3fef8a099930e901 ;double 0.98560027999999999
19 g_2: dq 0x40765876c8b43958 ;double 357.529
20 e_3: dq 0xbe9828c0be769dc1 ;double -3.5999999999999999E-7
21 e_4: dq 0x403770624dd2f1aa ;double 23.439
22 q_5: dq 0x3fef8a6c5512d6f2 ;double 0.98564735999999997
23 q_6: dq 0x4071875810624dd3 ;double 280.459
24 sing_1: dq 0x3FFEA3D70A3D70A4 ;double 1.915
25 sing_2: dq 0x3F947AE147AE147B ;double 0.020
26 RA_1: dq 0x402E000000000000 ;double 15.0
27 eqt_1: dq 0x4076800000000000 ;double 360.0
28 duhr_1: dq 0x4028000000000000 ;double 12.0
29 pray_1: dq 0x4038000000000000 ;double 24.0
30 neg1: dq 0xBFF0000000000000 ;double -1.0
31 p1: dq 0X3fb1111111111111 ;double 0.066666666666666666
32 sec_inhour: dq 0x40ac200000000000 ;double 3600
33 sec_inmin: dq 0x404e000000000000 ;double 60
34 maghrib_1: dq 0x3fa1c432ca57a787 ;double 0.0347
35 maghrib_2: dq 0x3feaaaaaaaaaaaab ;double 0.833333333333333333
36 isha_nor: dq 0x40b5180000000000 ;double 5400.0 90 min
37 isha_ram: dq 0x40bc200000000000 ;double 7200.0 120 min
39 section .bss
40 tmp0: resq 1
41 tmp1: resq 1
43 section .text
44 global _start
46 _start:
47 pop rcx
48 cmp rcx, MAX_ARGC
49 jl get_timestamp
50 je check_argv
52 die_usage:
53 DIE usage_msg, usage_len
55 check_argv:
56 mov r11, [rsp+8] ;argv
57 cmp [r11], byte 0x2d ;-
58 jne die_usage
59 cmp [r11+2], byte 0x00
60 jne die_usage
61 mov r12b, [r11+1]
62 cmp r12b, 0x75 ;u
63 je get_timestamp
64 cmp r12b, 0x6e ;n
65 je get_timestamp
66 cmp r12b, 0x76 ;v
67 jne die_usage
68 DIE version_msg, version_len
70 get_timestamp:
71 mov rax, SYS_gettimeofday ;sys_gettimeofday(
72 mov rdi, tmp0 ;struct timeval *tv,
73 mov rsi, rsi ;struct timezone* tz
74 syscall
76 ;start_of_day = tstamp - (tstamp % 86400);
77 mov edi, [tmp0]
78 movsx rax, edi
79 mov edx, edi
80 imul rax, rax, -1037155065
81 sar edx, 31
82 shr rax, 32
83 add eax, edi
84 sar eax, 16
85 sub eax, edx
86 imul edx, eax, 86400
87 mov eax, edi
88 sub eax, edx
89 cvtsi2sd xmm15, rdx
90 movsd xmm14, [time_zone]
91 mulsd xmm14, [sec_inhour]
92 subsd xmm15, xmm14
94 ;tstamp = xmm6 convert tstamp to double
95 cvtsi2sd xmm6, [tmp0]
97 ;julian = tstamp / sec_inday) + jul1970 = xmm0
98 movsd xmm0, xmm6 ;copy tstamp to xmm0
99 divsd xmm0, [sec_inday] ;tstamp / sec_inday
100 addsd xmm0, [jul1970] ;div result + jul1970
102 calc_equation_of_time:
103 ;d = julian - offset = xmm0
104 addsd xmm0, [offset]
106 ;g = to_rad * ((d * 0.98560028) + 357.529) = xmm1
107 movsd xmm1, [g_1]
108 mulsd xmm1, xmm0
109 addsd xmm1, [g_2]
110 mulsd xmm1, [to_rad]
112 ;e = to_rad * (23.439 - (d * 0.00000036)) = xmm3
113 movsd xmm3, [e_3]
114 mulsd xmm3, xmm0
115 addsd xmm3, [e_4]
116 mulsd xmm3, [to_rad]
118 ;q = (d * 0.98564736) + 280.459 = xmm4
119 movsd xmm4, [q_5]
120 mulsd xmm4, xmm0
121 addsd xmm4, [q_6]
123 ;sing = 1.915 * sin(g) = xmm5
124 movsd xmm5, xmm1
125 SIN xmm5
126 mulsd xmm5, [sing_1]
128 ;sin2g = 0.020 * sin(2.0*g) = xmm1
129 addsd xmm1, xmm1
130 SIN xmm1
131 mulsd xmm1, [sing_2]
133 ;sin(e) = xmm8
134 movsd xmm8 , xmm3
135 SIN xmm8
137 ;cos(e) = xmm7
138 movsd xmm7, xmm3
139 COS xmm7
141 ;L = to_rad(q + sing + sin2g) = xmm5
142 addsd xmm5, xmm1
143 addsd xmm5, xmm4
144 mulsd xmm5, [to_rad]
146 ;sin(L) = xmm2
147 movsd xmm2, xmm5
148 SIN xmm2
150 ;cos(L) = xmm5
151 COS xmm5
153 ;RA = to_deg(atan2(cose * sinL, cosL) / 15.0) = xmm7
154 mulsd xmm7, xmm2 ;cose * sinL
155 ATAN2 xmm7, xmm5 ;result in xmm7
156 divsd xmm7, [RA_1] ;atan2 result /15.0
157 mulsd xmm7, [to_deg] ;* to_deg
159 ;D = to_deg(asin(sine * sinL)) = xmm8
160 mulsd xmm8, xmm2
161 ASIN xmm8
162 mulsd xmm8, [to_deg]
164 ;EqT = q / 15.0 - RA = xmm9
165 movsd xmm9, xmm4 ;move q to xmm9
166 divsd xmm9, [RA_1] ;q / 15.0
167 subsd xmm9, xmm7 ;- RA
168 subsd xmm9, [eqt_1] ;EqT = EqT - 360.0
170 get_duhr: ;duhr = 12.0+time_zone-EqT-(longitude/15.0)=xmm0
171 movsd xmm1, [longitude]
172 divsd xmm1, [RA_1]
173 movsd xmm0, [duhr_1]
174 addsd xmm0, [time_zone]
175 subsd xmm0, xmm9
176 subsd xmm0, xmm1
177 NORM xmm0, [pray_1]
179 calc_p2p3:
180 CALC_P2 ;xmm1
181 CALC_P3 ;xmm2
183 get_fajr: ;fajr = duhr - T(fajr_angle, D) = xmm3
185 movsd xmm3, [fajr_angle]
186 CALC_T xmm3
188 ;fajr = duhr - T = xmm3
189 movsd xmm4, xmm3
190 movsd xmm3, xmm0
191 subsd xmm3, xmm4
193 test_fajr:
194 mulsd xmm3, [sec_inhour] ;convert to seconds
195 roundsd xmm3, xmm3, ROUND_DOWN
196 addsd xmm3, xmm15 ;fajr seconds + start_of_day
197 ucomisd xmm3, xmm6 ;if fajr > tstamp
198 jae print_fajr
200 test_duhr:
201 movsd xmm13, xmm0 ;save duhr to xmm13
202 mulsd xmm0, [sec_inhour] ;convert to seconds
203 roundsd xmm0, xmm0, ROUND_DOWN
204 addsd xmm0, xmm15 ;duhr seconds + start_of_day
205 ucomisd xmm0, xmm6 ;if duhr > tstamp
206 jae print_duhr
208 get_asr: ;asr = duhr + A(1.0, D);
209 ;A = p1 * p7 = xmm4
210 ;p4 = tan(convert_degrees_to_radians((latitude - D)))
211 ;p5 = atan2(1.0, (t + p4));
212 ;p6 = sin(p5) = xmm4
213 movsd xmm4, [latitude]
214 subsd xmm4, xmm8
215 mulsd xmm4, [to_rad]
216 movsd [tmp0], xmm4
217 fld1
218 fld qword [tmp0]
219 fptan
220 fadd
221 fpatan
222 fsin
223 fstp qword [tmp0]
224 movsd xmm4, [tmp0]
226 ;p7 = convert_radians_to_degrees(acos((p6 - p3) / p2));
227 subsd xmm4, xmm2
228 divsd xmm4, xmm1
229 ACOS xmm4
230 mulsd xmm4, [to_deg]
232 ;A = p1 * p7 = xmm4
233 mulsd xmm4, [p1]
234 addsd xmm4, xmm13
235 NORM xmm4, [pray_1]
237 test_asr:
238 mulsd xmm4, [sec_inhour] ;convert to seconds
239 roundsd xmm4, xmm4, ROUND_DOWN
240 addsd xmm4, xmm15 ;asr seconds + start_of_day
241 ucomisd xmm4, xmm6 ;if asr > tstamp
242 jae print_asr
244 get_maghrib: ;duhr + T(0.8333 + 0.0347 * sqrt(altitude), D) = xmm5
245 sqrtsd xmm5, [altitude]
246 mulsd xmm5, [maghrib_1]
247 addsd xmm5, [maghrib_2]
248 CALC_T xmm5
249 addsd xmm5, xmm13
251 test_maghrib:
252 mulsd xmm5, [sec_inhour] ;convert to seconds
253 roundsd xmm5, xmm5, ROUND_DOWN
254 addsd xmm5, xmm15 ;maghrib seconds + start_of_day
255 ucomisd xmm5, xmm6 ;if maghrib > tstamp
256 jae print_maghrib
258 get_isha:
259 mov rcx, 1
260 cmp rcx, use_umm_al_qura
261 jne um_nor
262 cmp rcx, ramadan
263 je um_ram
265 um_nor: ;maghrib + 90.0 min;
266 movsd xmm7, [isha_nor]
267 addsd xmm7, xmm5
268 jmp test_isha
270 um_ram: ;maghrib + 120.0 min;
271 movsd xmm7, [isha_ram]
272 addsd xmm7, xmm5
273 jmp test_isha
275 calc_isha_nor: ;duhr + T(isha_angle, D);
276 movsd xmm7, [isha_angle]
277 CALC_T xmm7
278 addsd xmm7, xmm13
279 NORM xmm7, [pray_1]
281 test_isha:
282 ucomisd xmm7, xmm6 ;if isha > tstamp
283 jae print_isha
285 get_nfajr: ;fajr + sec_inday
286 movsd xmm12, [sec_inday]
287 addsd xmm12, xmm3
289 print_nfajr:
290 mov [res_msg], byte 'F'
291 movsd xmm14, xmm12
292 cmp r12b, byte 'u'
293 je print_unix
295 subsd xmm12, xmm6 ;diff = prayer time - tstamp = xmm12
296 SEC_TO_HM xmm12
297 PRINT_EXIT
299 print_fajr:
300 mov [res_msg], byte 'F'
301 movsd xmm14, xmm3
302 cmp r12b, byte 'u'
303 je print_unix
304 subsd xmm3, xmm6 ;diff = prayer time - tstamp = xmm3
305 SEC_TO_HM xmm3
306 PRINT_EXIT
308 print_duhr:
309 mov [res_msg], byte 'D'
310 movsd xmm14, xmm0
311 cmp r12b, byte 'u'
312 je print_unix
313 cmp r12b, byte 'n'
314 je print_24
315 subsd xmm0, xmm6 ;diff = prayer time - tstamp = xmm0
316 SEC_TO_HM xmm0
317 PRINT_EXIT
319 print_asr:
320 mov [res_msg], byte 'A'
321 movsd xmm14, xmm4
322 cmp r12b, byte 'u'
323 je print_unix
324 cmp r12b, byte 'n'
325 je print_24
326 subsd xmm4, xmm6 ;diff = prayer time - tstamp = xmm4
327 SEC_TO_HM xmm4
328 PRINT_EXIT
330 print_maghrib:
331 mov [res_msg], byte 'M'
332 movsd xmm14, xmm5
333 cmp r12b, byte 'u'
334 je print_unix
335 cmp r12b, byte 'n'
336 je print_24
337 subsd xmm5, xmm6 ;diff = prayer time - tstamp = xmm5
338 SEC_TO_HM xmm5
339 PRINT_EXIT
341 print_isha:
342 mov [res_msg], byte 'I'
343 movsd xmm14, xmm7
344 cmp r12b, byte 'u'
345 je print_unix
346 cmp r12b, byte 'n'
347 je print_24
348 subsd xmm7, xmm6 ;diff = prayer time - tstamp = xmm7
349 SEC_TO_HM xmm7
350 PRINT_EXIT
352 print_unix:
353 PRINT_INT ;from xmm14
355 print_24:
356 subsd xmm14, xmm15 ;prayer timestamp - start_of_day
357 SEC_TO_HM xmm14
358 PRINT_EXIT
360 ; result_hour ;r8
361 ; result_min ;r9
362 ; duhr_ts: ;xmm0
363 ; p2: ;xmm1
364 ; p3: ;xmm2
365 ; fajr_ts: ;xmm3
366 ; asr_ts ;xmm4
367 ; maghrib_ts: ;xmm5
368 ; tstamp: ;xmm6
369 ; isha_ts: ;xmm7
370 ; D: ;xmm8
371 ; EqT: ;xmm9
372 ; macros: ;xmm10
373 ; next_fajr ;xmm12
374 ; duhr: ;xmm13
375 ; macros: ;xmm14
376 ; start_of_day: ;xmm15
378 EEXIT EXIT_SUCCESS