Compare commits
5 commits
921b7586d6
...
9e8417b7fb
Author | SHA1 | Date | |
---|---|---|---|
9e8417b7fb | |||
254c71f687 | |||
faaf5d2791 | |||
055357bfb8 | |||
4f74b3540c |
3 changed files with 234 additions and 34 deletions
12
Makefile
12
Makefile
|
@ -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
|
||||
|
||||
|
|
25
README.txt
25
README.txt
|
@ -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
|
||||
|
|
231
wtfstopw.asm
231
wtfstopw.asm
|
@ -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:
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue