Compare commits

...

10 commits

Author SHA1 Message Date
4432178af9 Bugfix for newline exit
When stdin is close instead of pressing enter
2018-09-10 02:40:38 +02:00
5929efa54b Reducing nop in allignement 2018-09-10 02:30:44 +02:00
8b63d50095 Argument parsing code enhancement
Using call & ret (but that's maybe not necessary...)
Reducing instruction size
2018-09-10 02:20:23 +02:00
36abef3e4e More main_loop and _start code enhancement 2018-09-10 02:19:32 +02:00
a675c1fd79 main_loop and _start proc enhancement
main_loop alignement and size reduction under 32 bytes
Size reduction of _start code
2018-09-09 19:01:01 +02:00
8b427138e0 Allign proc_print_time loops 2018-09-09 17:30:53 +02:00
511afacfe9 Add write error checks 2018-09-09 16:56:05 +02:00
0da7000028 Bugfix in sleep time calculation 2018-09-09 16:54:51 +02:00
9009013637 Reducing proc_print_time size
Using smaller operations
2018-09-09 16:53:29 +02:00
a6f66401cb Moved TIMESPEC data out of BSS 2018-09-09 16:44:09 +02:00

View file

@ -27,6 +27,8 @@
; press enter to exit ; press enter to exit
; send SIGINT (with kill -2 ir ctrl + c) for a new lap ; send SIGINT (with kill -2 ir ctrl + c) for a new lap
[bits 64] [bits 64]
%use smartalign
ALIGNMODE k8
%define O_NONBLOCK 0x800 %define O_NONBLOCK 0x800
@ -38,8 +40,8 @@ ENDSTRUC
%macro TIMESPEC 1 %macro TIMESPEC 1
%1: ISTRUC TIMESPEC_STRUC %1: ISTRUC TIMESPEC_STRUC
at TIMESPEC_STRUC.tv_sec, resq 1 at TIMESPEC_STRUC.tv_sec, dq 0
at TIMESPEC_STRUC.tv_nsec, resq 1 at TIMESPEC_STRUC.tv_nsec, dq 0
IEND IEND
%define %1.tv_sec %1+TIMESPEC_STRUC.tv_sec %define %1.tv_sec %1+TIMESPEC_STRUC.tv_sec
%define %1.tv_nsec %1+TIMESPEC_STRUC.tv_nsec %define %1.tv_nsec %1+TIMESPEC_STRUC.tv_nsec
@ -66,20 +68,15 @@ ENDSTRUC
%define sigaction.sa_mask sigaction+SIGACTION_STRUC.sa_mask %define sigaction.sa_mask sigaction+SIGACTION_STRUC.sa_mask
%endmacro %endmacro
section .bss section .data
align 8 align 8
TIMESPEC ts_start TIMESPEC ts_start
TIMESPEC ts_cur TIMESPEC ts_cur
TIMESPEC ts_sleep TIMESPEC ts_sleep
buf: resb 1
section .data
time_res: dq 2 ; 2 digits bellow seconds can grow to 8 time_res: dq 2 ; 2 digits bellow seconds can grow to 8
fcntl_flag: dq 0
SIGACTION sigaction
align 8
hours: times 8 db '0' ; 8 digits is the max for hours hours: times 8 db '0' ; 8 digits is the max for hours
timestr: db ":00:00." timestr: db ":00:00."
times 8 db '0' ; 8 digits for nanoseconds times 8 db '0' ; 8 digits for nanoseconds
@ -89,6 +86,11 @@ section .data
timestrlen: equ timestrend - timestr timestrlen: equ timestrend - timestr
%define HOURSLEN 8 %define HOURSLEN 8
buf: db 0
fcntl_flag: dq 0
SIGACTION sigaction
lapsmsg: db "Lap : " lapsmsg: db "Lap : "
lapsmsglen: equ $ - lapsmsg lapsmsglen: equ $ - lapsmsg
@ -134,8 +136,10 @@ global _start
_start: _start:
; parse arguments and set time_res value ; parse arguments and set time_res value
jmp arg_parse call arg_parse
arg_ok:
mov rbx, ts_start
%define RBXPTR(x) rbx + x - ts_start
; set stdin reads non blocking ; set stdin reads non blocking
xor rdx, rdx xor rdx, rdx
@ -143,26 +147,28 @@ xor rdi, rdi
mov rax, 72 ; fcntl mov rax, 72 ; fcntl
mov rsi, 3 ; F_GETFL mov rsi, 3 ; F_GETFL
syscall syscall
mov [fcntl_flag], rax mov [RBXPTR(fcntl_flag)], rax
mov rdx, rax mov rdx, rax
or rdx, O_NONBLOCK or dx, O_NONBLOCK
mov rax, 72 ; fcntl mov rax, 72 ; fcntl
mov rsi, 4 ; F_SETFL mov rsi, 4 ; F_SETFL
syscall syscall
cmp rax, 0 test al, al
jne fault js fault
; preparing SIGINT catch ; preparing SIGINT catch
mov rax, proc_lap_handler mov rax, proc_lap_handler
mov qword [sigaction.sa_handler], rax mov qword [RBXPTR(sigaction.sa_handler)], rax
mov eax, 0x14000000 ; SA_RESTART | SA_RESTORER mov ecx, 0x14000000 ; SA_RESTART | SA_RESTORER
mov dword [sigaction.sa_flags], eax mov dword [RBXPTR(sigaction.sa_flags)], ecx
mov rax, sig_restorer add rax, sig_restorer - proc_lap_handler
mov qword [sigaction.sa_restorer], rax mov qword [RBXPTR(sigaction.sa_restorer)], rax
mov rax, 13 ; sys_rt_sigaction mov rax, 13 ; sys_rt_sigaction
mov rdi, 2 ; SIGINT mov rdi, 2 ; SIGINT
mov rsi, sigaction mov rsi, rbx
add rsi, sigaction - ts_start
;mov rsi, sigaction
mov rdx, 0 ; NULL mov rdx, 0 ; NULL
mov r10, 8 ; sig_size mov r10, 8 ; sig_size
syscall syscall
@ -171,84 +177,91 @@ jne fault
mov rax, 228 ; clock_gettime mov rax, 228 ; clock_gettime
mov rdi, 0 ; CLOCK_REALTIME mov rdi, 0 ; CLOCK_REALTIME
mov rsi, ts_start mov rsi, rbx
syscall syscall
mov rax, 1 ; write mov rax, 1 ; write
mov rdi, 2 ; stderr mov rdi, 2 ; stderr
mov rsi, startmsg mov rsi, rbx
add rsi, startmsg - ts_start
mov rdx, startmsglen mov rdx, startmsglen
syscall syscall
; set value for ts_sleep.tv_nsec given time_res ; set value for ts_sleep.tv_nsec given time_res
; div sleep time by 10 for each digits added bellow seconds ; div sleep time by 10 for each digits added bellow seconds
mov qword [ts_sleep.tv_sec], 0
mov rax, 100000000 mov rax, 100000000
mov r8, [time_res] xor rcx, rcx
mov r9, 10 mov cl, [RBXPTR(time_res)]
dec cl
test cl, cl
jz setsleep_loopend
mov rsi, 10
xor rdx, rdx xor rdx, rdx
setsleep_loop: setsleep_loop:
cmp r8, 1 div rsi
jle setsleep_endloop loop setsleep_loop
div r9 setsleep_loopend:
sub r8, 1
jmp setsleep_loop mov [RBXPTR(ts_sleep.tv_nsec)], rax
setsleep_endloop: mov r12w, 0x0d02
mov [ts_sleep.tv_nsec], rax mov r13, proc_print_time
mov r14, buf ; nanosleep
mov r15, ts_sleep
std ; set DF for string operations std ; set DF for string operations
align 16
main_loop: main_loop:
push 2 ; stderr
push 0xD ; \r
call proc_print_time
; Attempt to read from stdin call r13 ; proc_print_time
; Attempt to read from stdin (syscall prepared by proc_print_time)
; if something read, enter has been pressed ; if something read, enter has been pressed
mov rax, 0
mov rdi, 0
mov rsi, buf
mov rdx, 1
syscall syscall
cmp rax, 0 test al, al
jge flush_stdin ; flush stdin and exit jns flush_stdin ; flush & exit
mov rax, 35 ; nanosleep mov rax, 35 ; nanosleep
mov rdi, ts_sleep mov rdi, r15
mov rsi, 0 xor rsi, rsi
syscall syscall
jmp main_loop ; main_loop jmp main_loop ; main_loop
flush_stdin: flush_stdin:
mov rax, 0 jz newline_exit
mov rdi, 0 xor rax, rax
mov rsi, buf ;xor rdi, rdi ; done in main_loop
mov rdx, 1 ;mov rsi, r14
;mov rdx, 1
syscall syscall
cmp rax, 0 test al, al
je newline_exit jns flush_stdin
jg flush_stdin
xor rbx, rbx ; EXIT OK
jmp exit
newline_exit:
mov rdi, 2 ; stderr
call proc_nl
xor rbx, rbx ; exit OK
jmp exit
mov rdi, 0 ; EXIT OK
; ;
; Expect rdi to be the return code ; Expect rbx to be the return code
; ;
exit: exit:
push rdi
; restoring stdin state ; restoring stdin state
mov rax, 72 ; fcntl mov rax, 72 ; fcntl
xor rdi, rdi xor rdi, rdi
mov rsi, 4 ; F_SETFL mov rsi, 4 ; F_SETFL
mov rdx, [fcntl_flag] mov rdx, [fcntl_flag]
syscall syscall
cmp rax, 0 mov rdi, rbx ; return code
je exit_end test rax, rax
pop rdi ; failed to restore cmovnz rdi, rax ; exit FAIL
push 1 ; exit FAIL
exit_end:
mov rax, 60 ; sys_exit mov rax, 60 ; sys_exit
pop rdi ; return code
syscall syscall
fault: fault:
mov rdi, 2 ; stderr mov rdi, 2 ; stderr
@ -258,76 +271,74 @@ fault:
mov rdx, faultmsglen mov rdx, faultmsglen
syscall syscall
mov rdi, 1 ; failure mov rbx, 1 ; failure
jmp exit jmp exit
newline_exit:
mov rdi, 1
call proc_nl
mov rdi, 0 ; exit OK
jmp exit
; ;
; Print current time on FD and add a leading char CHR ; Print current time on FD and add a leading char CHR
; push FD & push CHR to set arguments ; argument are in r12w r12b is FD and r12w(h) is CHR
; Warning : DF must be set ; Warning : DF must be set
; ;
align 16
proc_print_time: proc_print_time:
mov rax, 228 ; clock_gettime mov rax, 228 ; clock_gettime
mov rdi, 0 ; CLOCK_REALTIME xor rdi, rdi ; CLOCK_REALTIME
mov rsi, ts_cur mov rsi, ts_cur
syscall ; updating ts_cur time syscall ; updating ts_cur time
mov rax, [ts_cur.tv_nsec]
sub rax, [ts_start.tv_nsec] mov rsi, ts_start.tv_sec
cmp rax, 0 ; Calculating elapsed ns %define RSIPTR(x) rsi + x - ts_start.tv_sec
mov rax, [RSIPTR(ts_cur.tv_nsec)]
sub rax, [ts_start.tv_nsec] ; allign nano sec loop
jge print_time_us_cont jge print_time_us_cont
add rax, 1000000000 ; negativ result add rax, 1000000000 ; negativ result
sub qword [ts_cur.tv_sec], 1 sub qword [RSIPTR(ts_cur.tv_sec)], 1
print_time_us_cont: print_time_us_cont:
xor rdx, rdx xor rdx, rdx
div qword [ts_sleep.tv_nsec] ; Divide result given time_res div qword [RSIPTR(ts_sleep.tv_nsec)] ; Divide result given time_res
mov r9, [rsp + 8] mov bx, r12w
mov byte [timestr+timestrlen-1], r9b ; set last chr from 1st argument shr bx, 8
mov byte [RSIPTR(timestrend - 1)], bl ; set last chr from 1st argument
; set the nanosec chars (time_res chars) in timestr ; set the nanosec chars (time_res chars) in timestr
mov rbx, 0x2020202020202020 mov rbx, 0x2020202020202020
mov rcx, [time_res] mov rcx, [RSIPTR(time_res)]
mov r8, 10 mov rdi, 10
xor rdx, rdx
align 16 ; should be allready alligned
procpt_loopns: procpt_loopns:
xor rdx, rdx div rdi
div r8
or dl, 0x30 ; '0' or dl, 0x30 ; '0'
shl rbx, 8 shl rbx, 8
mov bl, dl xchg bl, dl
loop procpt_loopns loop procpt_loopns
mov [timestr+7], rbx mov [timestr+7], rbx
; filling timestr with seconds & minutes chars ; filling timestr with seconds & minutes chars
mov rax, [ts_cur.tv_sec] mov rax, [RSIPTR(ts_cur.tv_sec)]
sub rax, [ts_start.tv_sec] ; rax now contain elapsed seconds sub rax, [RSIPTR(ts_start.tv_sec)] ; rax now contain elapsed seconds
mov r8, 10 mov rcx, 10
mov r9, 6 mov rdi, 6
xor rdx, rdx xor rdx, rdx
div r8 div rcx
mov bh, dl mov bh, dl
xor dl, dl xor dl, dl
div r9 div rdi
mov bl, dl mov bl, dl
or bx, 0x3030 or bx, 0x3030
mov word [timestr + 4], bx mov word [timestr + 4], bx
xor dl, dl xor dl, dl
div r8 div rcx
mov bh, dl mov bh, dl
xor dl, dl xor dl, dl
div r9 div rdi
mov bl, dl mov bl, dl
or bx, 0x3030 or bx, 0x3030
mov word [timestr + 1], bx mov word [timestr + 1], bx
@ -335,38 +346,53 @@ proc_print_time:
; using rbx to stores the hours string ; using rbx to stores the hours string
xor rbx, rbx xor rbx, rbx
mov rcx, HOURSLEN mov rcx, HOURSLEN
mov r8, 10 mov rdi, 10
xor dl, dl
align 16
procpt_looph: procpt_looph:
xor dl, dl div rdi
div r8
shl rbx, 8 shl rbx, 8
mov bl, dl xchg bl, dl
cmp rax, 0 test rax, rax
loopne procpt_looph loopnz procpt_looph
procpt_looph_end:
mov r8, HOURSLEN - 2 xor rax, rax
cmp rcx, HOURSLEN - 2 mov al, HOURSLEN - 2
cmovl r8, rcx ; r8 stores hours digit count (at least 2) cmp cx, HOURSLEN - 2
cmp rcx, 0 cmovl ax, cx ; rax stores hours digit count (at least 2)
test cl, cl
jz procpt_looph2_end jz procpt_looph2_end
procpt_looph2: align 16
procpt_looph2: ; end rbx left shift before sto
shl rbx, 8 shl rbx, 8
loopne procpt_looph2 loopne procpt_looph2
procpt_looph2_end: procpt_looph2_end:
mov r9, 0x3030303030303030 ; ASCII convertion mov rdi, 0x3030303030303030 ; ASCII convertion
or rbx, r9 or rbx, rdi
mov [hours], rbx mov [RSIPTR(hours)], rbx
mov rax, 1 ; write xor rdi, rdi
mov rdi, [rsp + 16] ; fd as 2nd argument mov dil, r12b ; fd as 2nd argument
lea rsi, [hours + r8] ; hours start pointer
mov rdx, timestrlen + HOURSLEN mov rdx, timestrlen + HOURSLEN
sub rdx, r8 ; timestr + hours len sub rdx, rax ; timestr + hours len
lea rsi, [RSIPTR(hours + rax)] ; hours start pointer
mov rax, 1 ; write
syscall syscall
test rax, rax
js fault
; ALLIGN TRICK : prepare read syscall for main_loop
xor rax, rax
xor rdi, rdi
mov rsi, r14
mov rdx, 1
ret
%undef RSIPTR
ret 16
; ;
; sig handler for SIGINT displaying lap count and time on stdout ; sig handler for SIGINT displaying lap count and time on stdout
@ -377,12 +403,16 @@ proc_lap_handler:
mov rsi, cr mov rsi, cr
mov rdx, 1 mov rdx, 1
syscall ; \r on stderr syscall ; \r on stderr
test rax, rax
js fault
mov rax, 1 mov rax, 1
mov rdi, 1 mov rdi, 1
mov rsi, lapsmsg mov rsi, lapsmsg
mov rdx, 4 ; "Lap " mov rdx, 4 ; "Lap "
syscall syscall
test rax, rax
js fault
; increment the lapcount str directly ; increment the lapcount str directly
mov rcx, lapcountlen - 1; digit counter starting by the right most mov rcx, lapcountlen - 1; digit counter starting by the right most
@ -405,15 +435,18 @@ proc_lap_handler:
mov rax, 1 mov rax, 1
mov rdi, 1 ; stdout mov rdi, 1 ; stdout
syscall syscall
test rax, rax
js fault
mov rax, 1 ; write mov rax, 1 ; write
mov rsi, lapsmsg + 3 mov rsi, lapsmsg + 3
mov rdx, 3 ; " : " mov rdx, 3 ; " : "
syscall syscall
test rax, rax
js fault
std ; set DF for string operations std ; set DF for string operations
push 1 ; stdout mov r12w, 0x0A01 ; \n & stdout
push 0xA ; \n
call proc_print_time call proc_print_time
ret ret
@ -428,78 +461,80 @@ sig_restorer:
; ;
arg_parse: arg_parse:
; Checking argument count ; Checking argument count
mov rax, [rsp] mov rcx, [rsp+8] ; argc
cmp rax, 1 mov rsi, [rsp+24] ; argv[1]
mov rdi, badarg_msg
cmp rcx, 1
je arg_ok je arg_ok
cmp rax, 3 cmp rcx, 3
jle parse_r jle parse_r
arg_err: ; badval & badarg jmp here too arg_err: ; badval & badarg jmp here too
mov rax, [rsp+8] ; argv[0] program name mov rax, [rsp+16] ; argv[0] program name
mov rdi, -1 ; return status mov rdi, -1 ; return status
jmp usage jmp usage
parse_r: parse_r:
mov rax, [rsp+16] ; 1st arg should be "-r" mov rax, rsi
mov bl, [rax] cmp byte [rsi], '-'
cmp bl, '-'
jne badarg jne badarg
mov bl, [rax+1] mov bl, [rsi+1]
cmp bl, 'h' ; -h cmp bl, 'h' ; -h
je arg_err je arg_err
cmp bl, 'r' cmp bl, 'r'
jne badarg jne badarg
mov bl, [rax+2] cmp byte [rsi+2], 0
cmp bl, 0
jne arg_nxt ; the value seems to be just after the -r like -r2 jne arg_nxt ; the value seems to be just after the -r like -r2
nxt_arg: nxt_arg:
; the 1st argument is -r the second must be the time_res ; the 1st argument is -r the second must be the time_res
; check that the arg exists ; check that the arg exists
mov rax, [rsp] cmp cl, 3
cmp rax, 3
jne arg_err jne arg_err
mov rax, [rsp+24] mov rsi, [rsp+32]
jmp arg_cont jmp arg_cont
arg_nxt: arg_nxt:
; check that there is no more args ; check that there is no more args
mov rbx, [rsp] cmp cl, 2
cmp rbx, 2
jne arg_err jne arg_err
add rax, 2 add rsi, 2
arg_cont: arg_cont:
; rax should point on the value ; rsi should point on the ASCII digit counter
mov bl, [rax+1] cmp byte [rsi+1], 0
cmp bl, 0
jne badval jne badval
xor rbx, rbx xor rbx, rbx
mov bl, [rax] mov bl, [rsi]
cmp bl, '1' cmp bl, '1'
jl badval jl badval
cmp bl, '8' cmp bl, '8'
jg badval jg badval
sub bl, '0' xor bl, 0x30 ; '0'
mov [time_res], rbx mov [rdi + time_res - badarg_msg], rbx
jmp arg_ok
; print an error message, usage and exit with rax pointing the value arg_ok:
ret
; print an error message, usage and exit with rax pointing the value and
; rdi badarg_msg ptr
badval: badval:
mov rsi, badval_msg mov rbx, rsi
lea rsi, [rdi + badval_msg - badarg_msg]
mov rdx, badval_msglen mov rdx, badval_msglen
jmp arg_strerr jmp arg_strerr
; print an error message, usage and exit ; print an error message, usage and exit
badarg: badarg:
mov rsi, badarg_msg mov rbx, rsi
mov rsi, rdi
mov rdx, badarg_msglen mov rdx, badarg_msglen
mov rax, [rsp+16]
jmp arg_strerr jmp arg_strerr
; rsi msg ptr, rdx msg len, rax arg ptr ; rsi msg ptr, rdx msg len, rbx arg ptr
arg_strerr: arg_strerr:
mov r8, rax
mov rax, 1 mov rax, 1
mov rdi, 1 mov rdi, 1
syscall syscall
mov rsi, r8 mov rsi, rbx
mov rax, r8 mov rax, rbx
call proc_strlen call proc_strlen
mov rax, 1 mov rax, 1
syscall syscall