Compare commits

...

5 commits

3 changed files with 234 additions and 34 deletions

View file

@ -1,9 +1,17 @@
NASM=nasm
ASFLAGS=-felf64
LDFLAGS=-s -melf_x86_64
# To build with debugging symbols
#ASFLAGS=-felf64 -F dwarf -g
#LDFLAGS=-melf_x86_64
all: wtfstopw
wtfstopw: wtfstopw.o
ld -s -melf_x86_64 wtfstopw.o -o wtfstopw
ld $(LDFLAGS) wtfstopw.o -o wtfstopw
wtfstopw.o: wtfstopw.asm
nasm -felf64 wtfstopw.asm
$(NASM) $(ASFLAGS) wtfstopw.asm
.PHONY: clean

View file

@ -3,20 +3,27 @@ WTFStopW : a simple stopwatch
Build :
-------
make
make
or
nasm -felf64 wtfstopw.asm && ld -s -melf_x86_64 wtfstopw.o -o wtfstopw
nasm -felf64 wtfstopw.asm
ld -s -melf_x86_64 wtfstopw.o -o wtfstopw
Usage :
-------
./wtfstopw
./wtfstopw [-h] [-r NDIGITS]
Options :
---------
-h print an help message and exit
-r number of digits bellow seconds to display, default is 2
Interactions :
--------------
- press enter to exit or close stdin
- send SIGINT (with kill -2 or ctrl + c) for new lap on stdout
- elapsed time is sent on stderr and laps infos on stdout
press enter to exit or close stdin
send SIGINT (with kill -2 or ctrl + c) for new lap on stdout
elapsed time is sent on stderr and laps infos on stdout
Build with debugging symbols :
------------------------------
nasm -g -F dwarf -felf64 -l wtfstopw.lst wtfstopw.asm
ld -melf_x86_64 wtfstopw.o -o wtfstopw

View file

@ -17,12 +17,17 @@
;
; A simple precise stopwatch
; Build : nasm -felf64 wtfstopw.asm && ld -s -melf_x86_64 wtfstopw.o -o wtfstopw
; Build Debug : nasm -felf64 -l wtfstopw.lst wtfstopw.asm && ld -melf_x86_64 wtfstopw.o -o wtfstopw
;
; Usage : ./wtfstopw
; press enter to exit
; send SIGINT (with kill -2 or ctrl + c) for new lap on stdout
; Build Debug : nasm -g -F dwarf -felf64 -l wtfstopw.lst wtfstopw.asm && ld -melf_x86_64 wtfstopw.o -o wtfstopw
;
; ./wtfstopw [-h] [-r NDIGITS]
; Options :
; -h print this help and exit
; -r number of digits bellow seconds to display, default is 2
; Interact :
; press enter to exit
; send SIGINT (with kill -2 ir ctrl + c) for a new lap
[bits 64]
@ -32,10 +37,10 @@ STRUC TIMESPEC_STRUC
ENDSTRUC
%macro TIMESPEC 1
%macro TIMESPEC 3
%1: ISTRUC TIMESPEC_STRUC
at TIMESPEC_STRUC.tv_sec, dq 0
at TIMESPEC_STRUC.tv_nsec, dq 0
at TIMESPEC_STRUC.tv_sec, dq %2
at TIMESPEC_STRUC.tv_nsec, dq %3
IEND
%define %1.tv_sec %1+TIMESPEC_STRUC.tv_sec
%define %1.tv_nsec %1+TIMESPEC_STRUC.tv_nsec
@ -61,17 +66,9 @@ section .data
%define sigaction.sa_restorer sigaction+SIGACTION_STRUC.sa_restorer
%define sigaction.sa_mask sigaction+SIGACTION_STRUC.sa_mask
TIMESPEC ts_start
TIMESPEC ts_cur
ts_sleep:
tv_sleep_s dq 0
tv_sleep_us dq 10000000
;; 1/2s sleep
;ts_sleep:
; tv_sleep_s dq 0
; tv_sleep_us dq 500000000
TIMESPEC ts_start, 0, 0
TIMESPEC ts_cur, 0, 0
TIMESPEC ts_sleep, 0, 100000000 ; set before mainloop
faultmsg: db "Fault !", 0xA
@ -81,10 +78,34 @@ section .data
db 0xA
startmsglen: equ $ - startmsg
usage_pre: db "Usage : "
usage_prelen: equ $ - usage_pre
usage_post: db " [-h] [-r NDIGITS]", 0xA
db "Options :", 0xA
db 0x9, "-h print this help and exit", 0xA
db 0x9, "-r Number of digits bellow seconds, between [1..8]"
db 0xA
db "Interactions :", 0xA
db 0x9, "Press enter or close stdin to exit", 0xA
db 0x9, "Send SIGINT (with kill -2 or ctrl + c) for a new lap"
db 0xA
db 0x9, "Elapsed time is sent on stderr and laps infos on stdout"
db 0xA
usage_postlen: equ $ - usage_post
badarg_msg: db "Unexpected argument : "
badarg_msglen: equ $ - badarg_msg
badval_msg: db "Value for -r should be in [1..8] but got "
badval_msglen: equ $ - badval_msg
hours: db "000000000"
timestr: db ":00:00.0000 ", 0x0a
timestr: db ":00:00.0 ", 0x0a
timestrlen: equ $ - timestr
time_res: dq 2 ; 2 digits bellow seconds can grow to 8
nl: db 0x0A
buf: db 0
@ -101,6 +122,10 @@ section .text
global _start
_start:
; parse arguments and set time_res value
jmp arg_parse
arg_ok:
; set stdin non blocking
xor rdx, rdx
xor rdi, rdi
@ -146,6 +171,21 @@ mov rsi, startmsg
mov rdx, startmsglen
syscall
; set value for ts_sleep.tv_nsec given time_res
; div sleep time by 10 for each digits added bellow seconds
mov rax, 100000000
mov r8, [time_res]
mov r9, 10
xor rdx, rdx
setsleep_loop:
cmp r8, 1
jle setsleep_endloop
div r9
sub r8, 1
jmp setsleep_loop
setsleep_endloop:
mov [ts_sleep.tv_nsec], rax
main_loop:
push 2 ; stderr
push 0x0D ; \r
@ -254,13 +294,28 @@ proc_print_time:
sub rbx, 1
mov [ts_cur.tv_sec], rbx
print_time_us_cont:
; Divide result given time_res
mov r10, rax
mov rax, 1000000000
mov r9, [time_res]
mov r8, 10
xor rdx, rdx
print_time_respow:
div r8
sub r9, 1
cmp r9, 0
jg print_time_respow
mov rcx, rax
mov rax, r10
xor rdx, rdx
mov rcx, 100000
div rcx
; set the us char in timestr
mov r8, timestr
add r8, 10 ; r8 points on last char before \r
mov r9, 4 ; r9 count the number of digits
mov r9, [time_res] ; r9 count the number of digits
add r8, 6 ; first digits after seconds
add r8, r9 ; r8 points on last char before \r
print_time_us_loop:
xor rdx, rdx
mov rcx, 10
@ -415,4 +470,134 @@ sig_restorer:
xor rdi, rdi
syscall
;
; Argument parsing
;
arg_parse:
; Checking argument count
mov rax, [rsp]
cmp rax, 1
je arg_ok
cmp rax, 3
jle parse_r
arg_err: ; badval & badarg jmp here too
mov rax, [rsp+8] ; argv[0] program name
mov rdi, -1 ; return status
jmp usage
parse_r:
mov rax, [rsp+16] ; 1st arg should be "-r"
mov bl, [rax]
cmp bl, '-'
jne badarg
mov bl, [rax+1]
cmp bl, 'h' ; -h
je arg_err
cmp bl, 'r'
jne badarg
mov bl, [rax+2]
cmp bl, 0
jne arg_nxt ; the value seems to be just after the -r like -r2
nxt_arg:
; the 1st argument is -r the second must be the time_res
; check that the arg exists
mov rax, [rsp]
cmp rax, 3
jne arg_err
mov rax, [rsp+24]
jmp arg_cont
arg_nxt:
; check that there is no more args
mov rbx, [rsp]
cmp rbx, 2
jne arg_err
add rax, 2
arg_cont:
; rax should point on the value
mov bl, [rax+1]
cmp bl, 0
jne badval
xor rbx, rbx
mov bl, [rax]
cmp bl, '1'
jl badval
cmp bl, '8'
jg badval
sub bl, '0'
mov [time_res], rbx
jmp arg_ok
; print an error message, usage and exit with rax pointing the value
badval:
mov rsi, badval_msg
mov rdx, badval_msglen
jmp arg_strerr
; print an error message, usage and exit
badarg:
mov rsi, badarg_msg
mov rdx, badarg_msglen
mov rax, [rsp+16]
jmp arg_strerr
; rsi msg ptr, rdx msg len, rax arg ptr
arg_strerr:
mov r8, rax
mov rax, 1
mov rdi, 1
syscall
mov rsi, r8
mov rax, r8
call proc_strlen
mov rax, 1
syscall
mov rax, 1
mov rsi, nl
mov rdx, 1
syscall
syscall
jmp arg_err
;
; Print usage and exit
; Except rax to point on programm name and rdi to be the return code
;
usage:
push rdi
push rax
mov rax, 1 ; write
mov rdi, 1 ; stdout
mov rsi, usage_pre
mov rdx, usage_prelen
syscall
pop rsi
mov rax, rsi
call proc_strlen
mov rax, 1
syscall
mov rax, 1
mov rsi, usage_post
mov rdx, usage_postlen
syscall
mov rax, 60
pop rdi
syscall
; With rax pointing on the string, the result will be in rdx
proc_strlen:
mov r8, rax
mov r9, r8
sub r9, 1
strlen_loop:
add r9, 1
mov al, [r9]
cmp al, 0
jne strlen_loop
sub r9, r8
mov rdx, r9
ret
.end: