I wrote cat program in x64 FASM and I would like to know if there is anything that can be improved.
This implementation of cat supports:
- Reading from stdin.
- Multiple arguments.
I checked few cases and program behaves exactly like original cat command.
Is there anything I could do to improve performance of this program? I compared it to original cat and my program is around 200ms slower on 512MB file.
Code:
format ELF64 executable 3
entry start
BUFSIZE equ 1048576
segment readable writeable
fd dq 0
buf rb BUFSIZE
segment readable executable
start:
mov rbx, 1
cmp [rsp], rbx
je read
open:
xor rsi, rsi ;fd=open(pathname,flags)
mov rdi, [rsp+rbx*8+8]
mov rax, 2
syscall
mov [fd], rax
read:
mov rdx, BUFSIZE ;bytes_read=read(fd,buf,BUFSIZE)
mov rsi, buf
mov rdi, [fd]
mov rax, 0
syscall
write:
mov rdx, rax ;write(STDOUT_FILENO,buf,bytes_read)
mov rsi, buf
mov rdi, 1
mov rax, 1
syscall
test rdx, rdx ;if(bytes_read!=0) goto read
jnz read
close:
mov rdi, [fd] ;close(fd)
mov rax, 3
syscall
inc rbx
cmp rbx, [rsp] ;if(rbx<argc)
jb open
exit:
xor rdi, rdi
mov rax, 60
syscall
-
\$\begingroup\$ I have rolled back your last edit. Please don't change or add to the code in your question after you have received answers. See What should I do when someone answers my question? Thank you. \$\endgroup\$Martin R– Martin R2019年11月03日 09:40:39 +00:00Commented Nov 3, 2019 at 9:40
1 Answer 1
Linux has the sendfile
system call, which copies data between file descriptors instead of copying the data to userspace and back to kernel space. That may be more efficient.
Your code looks very clean and organized. If you had used named constants instead of magic numbers, you might not even need some of the comments:
mov rdx, tax
mov rsi, but
mov rdi, STDOUT_FILENO
mov rax, SYS_write
syscall
But I think even with these constants, the comments are still helpful, so I'd probably keep them anyway.
You should add error handling for stdout write errors, such as ENOSPACE
.
-
\$\begingroup\$ I wasn't aware of
sendfile
to be honest. I will try that and let you know if I see any difference in performance. My code looks very clean and organized thanks to other user. I wrote same program in x86 NASM before, but even back then my code wasn't that bad I think. These are not magic numbers as there are comments, but do you think its good idea to kinda rewrite needed constants that are defined in C and remove comments as everything will be clearly visible without them? \$\endgroup\$DeBos– DeBos2019年11月02日 19:50:53 +00:00Commented Nov 2, 2019 at 19:50 -
\$\begingroup\$ In relation to error handling, I'm firstly making program work, then optimizing it and adding error handling at the end. \$\endgroup\$DeBos– DeBos2019年11月02日 19:51:00 +00:00Commented Nov 2, 2019 at 19:51
-
\$\begingroup\$ I intentionally wrote "you might not need comments". I'd say just give it a try and see which variant looks nicer. :) \$\endgroup\$Roland Illig– Roland Illig2019年11月02日 23:13:49 +00:00Commented Nov 2, 2019 at 23:13
-
\$\begingroup\$ I added improved code to the question, so you can tell me which variant looks nicer/more readable/cleaner to you. Personally code without comments looks cleaner to me, but thats my code, so it will always be clean to me (until I will leave it for week and then come back later of course). \$\endgroup\$DeBos– DeBos2019年11月02日 23:34:41 +00:00Commented Nov 2, 2019 at 23:34
-
\$\begingroup\$ EDIT: you can find improved code here: pastebin.com/pS2ku0xz \$\endgroup\$DeBos– DeBos2019年11月03日 11:20:21 +00:00Commented Nov 3, 2019 at 11:20