|
@@ -17,12 +17,17 @@
|
17
|
17
|
;
|
18
|
18
|
; A simple precise stopwatch
|
19
|
19
|
; Build : nasm -felf64 wtfstopw.asm && ld -s -melf_x86_64 wtfstopw.o -o wtfstopw
|
20
|
|
-; Build Debug : nasm -felf64 -l wtfstopw.lst wtfstopw.asm && ld -melf_x86_64 wtfstopw.o -o wtfstopw
|
21
|
|
-;
|
22
|
|
-; Usage : ./wtfstopw
|
23
|
|
-; press enter to exit
|
24
|
|
-; send SIGINT (with kill -2 or ctrl + c) for new lap on stdout
|
|
20
|
+; Build Debug : nasm -g -F dwarf -felf64 -l wtfstopw.lst wtfstopw.asm && ld -melf_x86_64 wtfstopw.o -o wtfstopw
|
25
|
21
|
;
|
|
22
|
+; ./wtfstopw [-h] [-r NDIGITS]
|
|
23
|
+; Options :
|
|
24
|
+; -h print this help and exit
|
|
25
|
+; -r number of digits bellow seconds to display, default is 2
|
|
26
|
+; Interact :
|
|
27
|
+; press enter to exit
|
|
28
|
+; send SIGINT (with kill -2 ir ctrl + c) for a new lap
|
|
29
|
+
|
|
30
|
+
|
26
|
31
|
|
27
|
32
|
[bits 64]
|
28
|
33
|
|
|
@@ -32,10 +37,10 @@ STRUC TIMESPEC_STRUC
|
32
|
37
|
ENDSTRUC
|
33
|
38
|
|
34
|
39
|
|
35
|
|
-%macro TIMESPEC 1
|
|
40
|
+%macro TIMESPEC 3
|
36
|
41
|
%1: ISTRUC TIMESPEC_STRUC
|
37
|
|
- at TIMESPEC_STRUC.tv_sec, dq 0
|
38
|
|
- at TIMESPEC_STRUC.tv_nsec, dq 0
|
|
42
|
+ at TIMESPEC_STRUC.tv_sec, dq %2
|
|
43
|
+ at TIMESPEC_STRUC.tv_nsec, dq %3
|
39
|
44
|
IEND
|
40
|
45
|
%define %1.tv_sec %1+TIMESPEC_STRUC.tv_sec
|
41
|
46
|
%define %1.tv_nsec %1+TIMESPEC_STRUC.tv_nsec
|
|
@@ -61,17 +66,9 @@ section .data
|
61
|
66
|
%define sigaction.sa_restorer sigaction+SIGACTION_STRUC.sa_restorer
|
62
|
67
|
%define sigaction.sa_mask sigaction+SIGACTION_STRUC.sa_mask
|
63
|
68
|
|
64
|
|
- TIMESPEC ts_start
|
65
|
|
- TIMESPEC ts_cur
|
66
|
|
-
|
67
|
|
- ts_sleep:
|
68
|
|
- tv_sleep_s dq 0
|
69
|
|
- tv_sleep_us dq 10000000
|
70
|
|
-
|
71
|
|
- ;; 1/2s sleep
|
72
|
|
- ;ts_sleep:
|
73
|
|
- ; tv_sleep_s dq 0
|
74
|
|
- ; tv_sleep_us dq 500000000
|
|
69
|
+ TIMESPEC ts_start, 0, 0
|
|
70
|
+ TIMESPEC ts_cur, 0, 0
|
|
71
|
+ TIMESPEC ts_sleep, 0, 100000000 ; set before mainloop
|
75
|
72
|
|
76
|
73
|
|
77
|
74
|
faultmsg: db "Fault !", 0xA
|
|
@@ -81,10 +78,34 @@ section .data
|
81
|
78
|
db 0xA
|
82
|
79
|
startmsglen: equ $ - startmsg
|
83
|
80
|
|
|
81
|
+ usage_pre: db "Usage : "
|
|
82
|
+ usage_prelen: equ $ - usage_pre
|
|
83
|
+
|
|
84
|
+ usage_post: db " [-h] [-r NDIGITS]", 0xA
|
|
85
|
+ db "Options :", 0xA
|
|
86
|
+ db 0x9, "-h print this help and exit", 0xA
|
|
87
|
+ db 0x9, "-r Number of digits bellow seconds, between [1..8]"
|
|
88
|
+ db 0xA
|
|
89
|
+ db "Interactions :", 0xA
|
|
90
|
+ db 0x9, "Press enter or close stdin to exit", 0xA
|
|
91
|
+ db 0x9, "Send SIGINT (with kill -2 or ctrl + c) for a new lap"
|
|
92
|
+ db 0xA
|
|
93
|
+ db 0x9, "Elapsed time is sent on stderr and laps infos on stdout"
|
|
94
|
+ db 0xA
|
|
95
|
+ usage_postlen: equ $ - usage_post
|
|
96
|
+
|
|
97
|
+ badarg_msg: db "Unexpected argument : "
|
|
98
|
+ badarg_msglen: equ $ - badarg_msg
|
|
99
|
+
|
|
100
|
+ badval_msg: db "Value for -r should be in [1..8] but got "
|
|
101
|
+ badval_msglen: equ $ - badval_msg
|
|
102
|
+
|
84
|
103
|
hours: db "000000000"
|
85
|
|
- timestr: db ":00:00.0000 ", 0x0a
|
|
104
|
+ timestr: db ":00:00.0 ", 0x0a
|
86
|
105
|
timestrlen: equ $ - timestr
|
87
|
106
|
|
|
107
|
+ time_res: dq 2 ; 2 digits bellow seconds can grow to 8
|
|
108
|
+
|
88
|
109
|
nl: db 0x0A
|
89
|
110
|
buf: db 0
|
90
|
111
|
|
|
@@ -101,6 +122,10 @@ section .text
|
101
|
122
|
global _start
|
102
|
123
|
_start:
|
103
|
124
|
|
|
125
|
+; parse arguments and set time_res value
|
|
126
|
+jmp arg_parse
|
|
127
|
+arg_ok:
|
|
128
|
+
|
104
|
129
|
; set stdin non blocking
|
105
|
130
|
xor rdx, rdx
|
106
|
131
|
xor rdi, rdi
|
|
@@ -146,6 +171,21 @@ mov rsi, startmsg
|
146
|
171
|
mov rdx, startmsglen
|
147
|
172
|
syscall
|
148
|
173
|
|
|
174
|
+; set value for ts_sleep.tv_nsec given time_res
|
|
175
|
+; div sleep time by 10 for each digits added bellow seconds
|
|
176
|
+mov rax, 100000000
|
|
177
|
+mov r8, [time_res]
|
|
178
|
+mov r9, 10
|
|
179
|
+xor rdx, rdx
|
|
180
|
+setsleep_loop:
|
|
181
|
+ cmp r8, 1
|
|
182
|
+ jle setsleep_endloop
|
|
183
|
+ div r9
|
|
184
|
+ sub r8, 1
|
|
185
|
+ jmp setsleep_loop
|
|
186
|
+setsleep_endloop:
|
|
187
|
+mov [ts_sleep.tv_nsec], rax
|
|
188
|
+
|
149
|
189
|
main_loop:
|
150
|
190
|
push 2 ; stderr
|
151
|
191
|
push 0x0D ; \r
|
|
@@ -254,13 +294,28 @@ proc_print_time:
|
254
|
294
|
sub rbx, 1
|
255
|
295
|
mov [ts_cur.tv_sec], rbx
|
256
|
296
|
print_time_us_cont:
|
|
297
|
+
|
|
298
|
+ ; Divide result given time_res
|
|
299
|
+ mov r10, rax
|
|
300
|
+ mov rax, 1000000000
|
|
301
|
+ mov r9, [time_res]
|
|
302
|
+ mov r8, 10
|
|
303
|
+ xor rdx, rdx
|
|
304
|
+ print_time_respow:
|
|
305
|
+ div r8
|
|
306
|
+ sub r9, 1
|
|
307
|
+ cmp r9, 0
|
|
308
|
+ jg print_time_respow
|
|
309
|
+ mov rcx, rax
|
|
310
|
+ mov rax, r10
|
257
|
311
|
xor rdx, rdx
|
258
|
|
- mov rcx, 100000
|
259
|
312
|
div rcx
|
|
313
|
+
|
260
|
314
|
; set the us char in timestr
|
261
|
315
|
mov r8, timestr
|
262
|
|
- add r8, 10 ; r8 points on last char before \r
|
263
|
|
- mov r9, 4 ; r9 count the number of digits
|
|
316
|
+ mov r9, [time_res] ; r9 count the number of digits
|
|
317
|
+ add r8, 6 ; first digits after seconds
|
|
318
|
+ add r8, r9 ; r8 points on last char before \r
|
264
|
319
|
print_time_us_loop:
|
265
|
320
|
xor rdx, rdx
|
266
|
321
|
mov rcx, 10
|
|
@@ -415,4 +470,134 @@ sig_restorer:
|
415
|
470
|
xor rdi, rdi
|
416
|
471
|
syscall
|
417
|
472
|
|
|
473
|
+;
|
|
474
|
+; Argument parsing
|
|
475
|
+;
|
|
476
|
+arg_parse:
|
|
477
|
+ ; Checking argument count
|
|
478
|
+ mov rax, [rsp]
|
|
479
|
+ cmp rax, 1
|
|
480
|
+ je arg_ok
|
|
481
|
+ cmp rax, 3
|
|
482
|
+ jle parse_r
|
|
483
|
+ arg_err: ; badval & badarg jmp here too
|
|
484
|
+ mov rax, [rsp+8] ; argv[0] program name
|
|
485
|
+ mov rdi, -1 ; return status
|
|
486
|
+ jmp usage
|
|
487
|
+ parse_r:
|
|
488
|
+ mov rax, [rsp+16] ; 1st arg should be "-r"
|
|
489
|
+ mov bl, [rax]
|
|
490
|
+ cmp bl, '-'
|
|
491
|
+ jne badarg
|
|
492
|
+ mov bl, [rax+1]
|
|
493
|
+ cmp bl, 'h' ; -h
|
|
494
|
+ je arg_err
|
|
495
|
+ cmp bl, 'r'
|
|
496
|
+ jne badarg
|
|
497
|
+ mov bl, [rax+2]
|
|
498
|
+ cmp bl, 0
|
|
499
|
+ jne arg_nxt ; the value seems to be just after the -r like -r2
|
|
500
|
+ nxt_arg:
|
|
501
|
+ ; the 1st argument is -r the second must be the time_res
|
|
502
|
+ ; check that the arg exists
|
|
503
|
+ mov rax, [rsp]
|
|
504
|
+ cmp rax, 3
|
|
505
|
+ jne arg_err
|
|
506
|
+ mov rax, [rsp+24]
|
|
507
|
+ jmp arg_cont
|
|
508
|
+ arg_nxt:
|
|
509
|
+ ; check that there is no more args
|
|
510
|
+ mov rbx, [rsp]
|
|
511
|
+ cmp rbx, 2
|
|
512
|
+ jne arg_err
|
|
513
|
+ add rax, 2
|
|
514
|
+ arg_cont:
|
|
515
|
+ ; rax should point on the value
|
|
516
|
+ mov bl, [rax+1]
|
|
517
|
+ cmp bl, 0
|
|
518
|
+ jne badval
|
|
519
|
+ xor rbx, rbx
|
|
520
|
+ mov bl, [rax]
|
|
521
|
+ cmp bl, '1'
|
|
522
|
+ jl badval
|
|
523
|
+ cmp bl, '8'
|
|
524
|
+ jg badval
|
|
525
|
+ sub bl, '0'
|
|
526
|
+ mov [time_res], rbx
|
|
527
|
+ jmp arg_ok
|
|
528
|
+
|
|
529
|
+; print an error message, usage and exit with rax pointing the value
|
|
530
|
+badval:
|
|
531
|
+ mov rsi, badval_msg
|
|
532
|
+ mov rdx, badval_msglen
|
|
533
|
+ jmp arg_strerr
|
|
534
|
+
|
|
535
|
+; print an error message, usage and exit
|
|
536
|
+badarg:
|
|
537
|
+ mov rsi, badarg_msg
|
|
538
|
+ mov rdx, badarg_msglen
|
|
539
|
+ mov rax, [rsp+16]
|
|
540
|
+ jmp arg_strerr
|
|
541
|
+
|
|
542
|
+; rsi msg ptr, rdx msg len, rax arg ptr
|
|
543
|
+arg_strerr:
|
|
544
|
+ mov r8, rax
|
|
545
|
+ mov rax, 1
|
|
546
|
+ mov rdi, 1
|
|
547
|
+ syscall
|
|
548
|
+ mov rsi, r8
|
|
549
|
+ mov rax, r8
|
|
550
|
+ call proc_strlen
|
|
551
|
+ mov rax, 1
|
|
552
|
+ syscall
|
|
553
|
+ mov rax, 1
|
|
554
|
+ mov rsi, nl
|
|
555
|
+ mov rdx, 1
|
|
556
|
+ syscall
|
|
557
|
+ syscall
|
|
558
|
+ jmp arg_err
|
|
559
|
+
|
|
560
|
+;
|
|
561
|
+; Print usage and exit
|
|
562
|
+; Except rax to point on programm name and rdi to be the return code
|
|
563
|
+;
|
|
564
|
+usage:
|
|
565
|
+ push rdi
|
|
566
|
+ push rax
|
|
567
|
+
|
|
568
|
+ mov rax, 1 ; write
|
|
569
|
+ mov rdi, 1 ; stdout
|
|
570
|
+ mov rsi, usage_pre
|
|
571
|
+ mov rdx, usage_prelen
|
|
572
|
+ syscall
|
|
573
|
+
|
|
574
|
+ pop rsi
|
|
575
|
+ mov rax, rsi
|
|
576
|
+ call proc_strlen
|
|
577
|
+ mov rax, 1
|
|
578
|
+ syscall
|
|
579
|
+
|
|
580
|
+ mov rax, 1
|
|
581
|
+ mov rsi, usage_post
|
|
582
|
+ mov rdx, usage_postlen
|
|
583
|
+ syscall
|
|
584
|
+
|
|
585
|
+ mov rax, 60
|
|
586
|
+ pop rdi
|
|
587
|
+ syscall
|
|
588
|
+
|
|
589
|
+; With rax pointing on the string, the result will be in rdx
|
|
590
|
+proc_strlen:
|
|
591
|
+ mov r8, rax
|
|
592
|
+ mov r9, r8
|
|
593
|
+ sub r9, 1
|
|
594
|
+ strlen_loop:
|
|
595
|
+ add r9, 1
|
|
596
|
+ mov al, [r9]
|
|
597
|
+ cmp al, 0
|
|
598
|
+ jne strlen_loop
|
|
599
|
+ sub r9, r8
|
|
600
|
+ mov rdx, r9
|
|
601
|
+ ret
|
|
602
|
+
|
418
|
603
|
.end:
|