6
\$\begingroup\$

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
\$\endgroup\$
1

1 Answer 1

4
\$\begingroup\$

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.

\$\endgroup\$
5
  • \$\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
    Commented 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
    Commented 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\$ Commented 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
    Commented Nov 2, 2019 at 23:34
  • \$\begingroup\$ EDIT: you can find improved code here: pastebin.com/pS2ku0xz \$\endgroup\$
    – DeBos
    Commented Nov 3, 2019 at 11:20

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.