azan

prayers time calculator written in nasm x86-64
git clone https://git.afify.dev/azan.git
Log | Files | Refs | README | LICENSE

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