azan.s (9959B)
1 ; See LICENSE file for copyright and license details. 2 ; azan is simple muslim prayers calculator. 3 ; print next prayer left duration or today's all prayers. 4 5 BITS 64 6 %include "syscalls.s" 7 %include "macros.s" 8 %include "math.s" 9 %include "config.s" 10 CHECK_BSD 11 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 38 usage_msg: db "usage: azan [-AaNnUuv]", 10, 0 39 usage_len: equ $ - usage_msg 40 version_msg: db "azan-", VERSION, 10, 0 41 version_len: equ $ - version_msg 42 pledge_msg: db "pledge", 10, 0 43 promises: db "stdio", 0 44 45 section .data 46 res_msg: db "X XX:XX", 10, 0 47 res_len: equ $ - res_msg 48 49 section .bss 50 tmp0: resq 1 51 tmp1: resq 1 52 53 section .text 54 global _start 55 56 _start: 57 pop rcx 58 cmp rcx, MAX_ARGC 59 jl get_timestamp 60 je check_argv 61 62 die_usage: 63 DIE usage_msg, usage_len 64 65 check_argv: 66 mov r11, [rsp+8] ;argv 67 cmp [r11], byte 0x2d ;- 68 jne die_usage 69 cmp [r11+2], byte 0x00 70 jne die_usage 71 mov r12b, [r11+1] 72 cmp r12b, 0x41 ;A 73 je get_timestamp 74 cmp r12b, 0x61 ;a 75 je get_timestamp 76 cmp r12b, 0x55 ;U 77 je get_timestamp 78 cmp r12b, 0x75 ;u 79 je get_timestamp 80 cmp r12b, 0x6e ;n 81 je get_timestamp 82 cmp r12b, 0x4e ;N 83 je get_timestamp 84 cmp r12b, 0x76 ;v 85 jne die_usage 86 DIE version_msg, version_len 87 88 get_timestamp: 89 OPENBSD_PLEDGE 90 mov rax, SYS_gettimeofday ;sys_gettimeofday( 91 mov rdi, tmp0 ;struct timeval *tv, 92 mov rsi, rsi ;struct timezone* tz 93 syscall 94 95 ;start_of_day = tstamp - (tstamp % 86400); 96 mov edi, [tmp0] 97 movsx rax, edi 98 mov edx, edi 99 imul rax, rax, -1037155065 100 sar edx, 31 101 shr rax, 32 102 add eax, edi 103 sar eax, 16 104 sub eax, edx 105 imul edx, eax, 86400 106 mov eax, edi 107 sub eax, edx 108 cvtsi2sd xmm15, rdx 109 movsd xmm14, [time_zone] 110 mulsd xmm14, [sec_inhour] 111 subsd xmm15, xmm14 112 113 ;tstamp = xmm6 convert tstamp to double 114 cvtsi2sd xmm6, [tmp0] 115 116 ;julian = tstamp / sec_inday) + jul1970 = xmm0 117 movsd xmm0, xmm6 ;copy tstamp to xmm0 118 divsd xmm0, [sec_inday] ;tstamp / sec_inday 119 addsd xmm0, [jul1970] ;div result + jul1970 120 121 calc_equation_of_time: 122 ;d = julian - offset = xmm0 123 addsd xmm0, [offset] 124 125 ;g = to_rad * ((d * 0.98560028) + 357.529) = xmm1 126 movsd xmm1, [g_1] 127 mulsd xmm1, xmm0 128 addsd xmm1, [g_2] 129 mulsd xmm1, [to_rad] 130 131 ;e = to_rad * (23.439 - (d * 0.00000036)) = xmm3 132 movsd xmm3, [e_3] 133 mulsd xmm3, xmm0 134 addsd xmm3, [e_4] 135 mulsd xmm3, [to_rad] 136 137 ;q = (d * 0.98564736) + 280.459 = xmm4 138 movsd xmm4, [q_5] 139 mulsd xmm4, xmm0 140 addsd xmm4, [q_6] 141 142 ;sing = 1.915 * sin(g) = xmm5 143 movsd xmm5, xmm1 144 SIN xmm5 145 mulsd xmm5, [sing_1] 146 147 ;sin2g = 0.020 * sin(2.0*g) = xmm1 148 addsd xmm1, xmm1 149 SIN xmm1 150 mulsd xmm1, [sing_2] 151 152 ;sin(e) = xmm8 153 movsd xmm8 , xmm3 154 SIN xmm8 155 156 ;cos(e) = xmm7 157 movsd xmm7, xmm3 158 COS xmm7 159 160 ;L = to_rad(q + sing + sin2g) = xmm5 161 addsd xmm5, xmm1 162 addsd xmm5, xmm4 163 mulsd xmm5, [to_rad] 164 165 ;sin(L) = xmm2 166 movsd xmm2, xmm5 167 SIN xmm2 168 169 ;cos(L) = xmm5 170 COS xmm5 171 172 ;RA = to_deg(atan2(cose * sinL, cosL) / 15.0) = xmm7 173 mulsd xmm7, xmm2 ;cose * sinL 174 ATAN2 xmm7, xmm5 ;result in xmm7 175 divsd xmm7, [RA_1] ;atan2 result /15.0 176 mulsd xmm7, [to_deg] ;* to_deg 177 178 ;D = to_deg(asin(sine * sinL)) = xmm8 179 mulsd xmm8, xmm2 180 ASIN xmm8 181 mulsd xmm8, [to_deg] 182 183 ;EqT = q / 15.0 - RA = xmm9 184 movsd xmm9, xmm4 ;move q to xmm9 185 divsd xmm9, [RA_1] ;q / 15.0 186 subsd xmm9, xmm7 ;- RA 187 subsd xmm9, [eqt_1] ;EqT = EqT - 360.0 188 189 get_duhr: ;duhr = 12.0+time_zone-EqT-(longitude/15.0)=xmm0 190 movsd xmm1, [longitude] 191 divsd xmm1, [RA_1] 192 movsd xmm0, [duhr_1] 193 addsd xmm0, [time_zone] 194 subsd xmm0, xmm9 195 subsd xmm0, xmm1 196 NORM xmm0, [pray_1] 197 198 calc_p2p3: 199 CALC_P2 ;xmm1 200 CALC_P3 ;xmm2 201 202 get_fajr: ;fajr = duhr - T(fajr_angle, D) = xmm3 203 204 movsd xmm3, [fajr_angle] 205 CALC_T xmm3 206 207 ;fajr = duhr - T = xmm3 208 movsd xmm4, xmm3 209 movsd xmm3, xmm0 210 subsd xmm3, xmm4 211 212 test_fajr: 213 mulsd xmm3, [sec_inhour] ;convert to seconds 214 roundsd xmm3, xmm3, ROUND_DOWN 215 addsd xmm3, xmm15 ;fajr seconds + start_of_day 216 cmp r12b, byte 'U' 217 je test_duhr 218 cmp r12b, byte 'a' 219 je test_duhr 220 cmp r12b, byte 'A' 221 je test_duhr 222 ucomisd xmm3, xmm6 ;if fajr > tstamp 223 jae print_fajr 224 225 test_duhr: 226 movsd xmm13, xmm0 ;save duhr to xmm13 227 mulsd xmm0, [sec_inhour] ;convert to seconds 228 roundsd xmm0, xmm0, ROUND_DOWN 229 addsd xmm0, xmm15 ;duhr seconds + start_of_day 230 cmp r12b, byte 'U' 231 je get_asr 232 cmp r12b, byte 'a' 233 je get_asr 234 cmp r12b, byte 'A' 235 je get_asr 236 ucomisd xmm0, xmm6 ;if duhr > tstamp 237 jae print_duhr 238 239 get_asr: ;asr = duhr + A(1.0, D); 240 ;A = p1 * p7 = xmm4 241 ;p4 = tan(convert_degrees_to_radians((latitude - D))) 242 ;p5 = atan2(1.0, (t + p4)); 243 ;p6 = sin(p5) = xmm4 244 movsd xmm4, [latitude] 245 subsd xmm4, xmm8 246 mulsd xmm4, [to_rad] 247 movsd [tmp0], xmm4 248 fld1 249 fld qword [tmp0] 250 fptan 251 fadd 252 fpatan 253 fsin 254 fstp qword [tmp0] 255 movsd xmm4, [tmp0] 256 257 ;p7 = convert_radians_to_degrees(acos((p6 - p3) / p2)); 258 subsd xmm4, xmm2 259 divsd xmm4, xmm1 260 ACOS xmm4 261 mulsd xmm4, [to_deg] 262 263 ;A = p1 * p7 = xmm4 264 mulsd xmm4, [p1] 265 addsd xmm4, xmm13 266 NORM xmm4, [pray_1] 267 268 test_asr: 269 mulsd xmm4, [sec_inhour] ;convert to seconds 270 roundsd xmm4, xmm4, ROUND_DOWN 271 addsd xmm4, xmm15 ;asr seconds + start_of_day 272 cmp r12b, byte 'U' 273 je get_maghrib 274 cmp r12b, byte 'a' 275 je get_maghrib 276 cmp r12b, byte 'A' 277 je get_maghrib 278 ucomisd xmm4, xmm6 ;if asr > tstamp 279 jae print_asr 280 281 get_maghrib: ;duhr + T(0.8333 + 0.0347 * sqrt(altitude), D) = xmm5 282 sqrtsd xmm5, [altitude] 283 mulsd xmm5, [maghrib_1] 284 addsd xmm5, [maghrib_2] 285 CALC_T xmm5 286 addsd xmm5, xmm13 287 288 test_maghrib: 289 mulsd xmm5, [sec_inhour] ;convert to seconds 290 roundsd xmm5, xmm5, ROUND_DOWN 291 addsd xmm5, xmm15 ;maghrib seconds + start_of_day 292 cmp r12b, byte 'U' 293 je get_isha 294 cmp r12b, byte 'a' 295 je get_isha 296 cmp r12b, byte 'A' 297 je get_isha 298 ucomisd xmm5, xmm6 ;if maghrib > tstamp 299 jae print_maghrib 300 301 get_isha: 302 mov rcx, 1 303 cmp rcx, use_umm_al_qura 304 jne um_nor 305 cmp rcx, ramadan 306 je um_ram 307 308 um_nor: ;maghrib + 90.0 min; 309 movsd xmm7, [isha_nor] 310 addsd xmm7, xmm5 311 jmp test_isha 312 313 um_ram: ;maghrib + 120.0 min; 314 movsd xmm7, [isha_ram] 315 addsd xmm7, xmm5 316 jmp test_isha 317 318 calc_isha_nor: ;duhr + T(isha_angle, D); 319 movsd xmm7, [isha_angle] 320 CALC_T xmm7 321 addsd xmm7, xmm13 322 NORM xmm7, [pray_1] 323 324 test_isha: 325 cmp r12b, byte 'U' 326 je print_all_u 327 cmp r12b, byte 'a' 328 je print_all_24 329 cmp r12b, byte 'A' 330 je print_all_12 331 ucomisd xmm7, xmm6 ;if isha > tstamp 332 jae print_isha 333 334 get_nfajr: ;fajr + sec_inday 335 movsd xmm12, [sec_inday] 336 addsd xmm12, xmm3 337 338 print_nfajr: 339 mov [res_msg], byte 'F' 340 movsd xmm14, xmm12 341 cmp r12b, byte 'u' 342 je print_unix 343 cmp r12b, byte 'n' 344 je print_fajr 345 cmp r12b, byte 'N' 346 je print_fajr 347 subsd xmm12, xmm6 ;diff = prayer time - tstamp = xmm12 348 SEC_TO_HM xmm12 349 PRINT_HM 350 EEXIT EXIT_SUCCESS 351 352 print_fajr: 353 mov [res_msg], byte 'F' 354 PRINT_FLAG xmm3 355 356 print_duhr: 357 mov [res_msg], byte 'D' 358 PRINT_FLAG xmm0 359 360 print_asr: 361 mov [res_msg], byte 'A' 362 PRINT_FLAG xmm4 363 364 print_maghrib: 365 mov [res_msg], byte 'M' 366 PRINT_FLAG xmm5 367 368 print_isha: 369 mov [res_msg], byte 'I' 370 PRINT_FLAG xmm7 371 372 print_unix: 373 PRINT_INT xmm14 374 EEXIT EXIT_SUCCESS 375 376 print_24: 377 subsd xmm14, xmm15 ;prayer timestamp - start_of_day 378 SEC_TO_HM xmm14 379 PRINT_HM 380 EEXIT EXIT_SUCCESS 381 382 print_12: 383 subsd xmm14, xmm15 ;prayer timestamp - start_of_day 384 SEC_TO_HM xmm14 385 cmp r8, 0xc 386 jle print_exit 387 sub r8, 0xc 388 389 print_exit: 390 PRINT_HM 391 EEXIT EXIT_SUCCESS 392 393 print_all_u: 394 PRINT_INT xmm3 ;fajr 395 PRINT_INT xmm0 ;duhr 396 PRINT_INT xmm4 ;asr 397 PRINT_INT xmm5 ;maghrib 398 PRINT_INT xmm7 ;isha 399 EEXIT EXIT_SUCCESS 400 401 print_all_24: 402 mov [res_msg], byte 'F' 403 subsd xmm3, xmm15 ;prayer timestamp - start_of_day 404 SEC_TO_HM xmm3 405 PRINT_HM 406 407 mov [res_msg], byte 'D' 408 subsd xmm0, xmm15 ;prayer timestamp - start_of_day 409 SEC_TO_HM xmm0 410 PRINT_HM 411 412 mov [res_msg], byte 'A' 413 subsd xmm4, xmm15 ;prayer timestamp - start_of_day 414 SEC_TO_HM xmm4 415 PRINT_HM 416 417 mov [res_msg], byte 'M' 418 subsd xmm5, xmm15 ;prayer timestamp - start_of_day 419 SEC_TO_HM xmm5 420 PRINT_HM 421 422 mov [res_msg], byte 'I' 423 subsd xmm7, xmm15 ;prayer timestamp - start_of_day 424 SEC_TO_HM xmm7 425 PRINT_HM 426 EEXIT EXIT_SUCCESS 427 428 print_all_12: 429 mov [res_msg], byte 'F' 430 subsd xmm3, xmm15 ;prayer timestamp - start_of_day 431 SEC_TO_HM xmm3 432 PRINT_HM 433 434 mov [res_msg], byte 'D' 435 subsd xmm0, xmm15 ;prayer timestamp - start_of_day 436 SEC_TO_HM xmm0 437 PRINT_HM 438 439 mov [res_msg], byte 'A' 440 subsd xmm4, xmm15 ;prayer timestamp - start_of_day 441 SEC_TO_HM xmm4 442 sub r8, 0xc 443 PRINT_HM 444 445 mov [res_msg], byte 'M' 446 subsd xmm5, xmm15 ;prayer timestamp - start_of_day 447 SEC_TO_HM xmm5 448 sub r8, 0xc 449 PRINT_HM 450 451 mov [res_msg], byte 'I' 452 subsd xmm7, xmm15 ;prayer timestamp - start_of_day 453 SEC_TO_HM xmm7 454 sub r8, 0xc 455 PRINT_HM 456 EEXIT EXIT_SUCCESS 457 458 die_pledge: 459 DIE pledge_msg, 8 460 ; result_hour ;r8 461 ; result_min ;r9 462 ; duhr_ts: ;xmm0 463 ; p2: ;xmm1 464 ; p3: ;xmm2 465 ; fajr_ts: ;xmm3 466 ; asr_ts ;xmm4 467 ; maghrib_ts: ;xmm5 468 ; tstamp: ;xmm6 469 ; isha_ts: ;xmm7 470 ; D: ;xmm8 471 ; EqT: ;xmm9 472 ; macros: ;xmm10 473 ; next_fajr ;xmm12 474 ; duhr: ;xmm13 475 ; macros: ;xmm14 476 ; start_of_day: ;xmm15