; Version : 1.0 ; Updated : 28/10/2020 ; Description : cat(1) in assembly ; Copyright (C) : 2020, 2021 Gentoo-libre Install ; License : GPLv3+ section .bss Buff resb 16384 ;read data up to 16384 bytes at a time bufflen equ $-Buff section .data section .text global _start _start: pop rsi ;Pop number of args from the stack cmp esi,1 je stdin ;go to stdin mode if there are no arguments pop rsi ;discard argv[0] nextarg: pop rsi ;get pointer to argv[x] ; we could use argc as a loop counter, but we can just check to see if we popped a zero intead test rsi, rsi jz exit ; open each file for reading open: mov eax, 2 ;sys_open mov rdi, rsi ;filename = pointer to null terminated filename xor esi, esi ;O_RDONLY xor edx, edx ;don't set a mode syscall ; the result is returned in rax test rax, rax js nextarg ;get the next argv if rax is negative (as the file couldn't be opened) copy: mov edi, eax ;move the fd to rdi for read mov r15, rax ;copy the fd to an AMD64 additional register for safekeeping call read output: mov edi, 1 ;stdout mov edx, eax ;rax contains the number of bytes read call write mov ecx, eax ;copy the amount written to a different register mov rax, r15 ;copy the fd back to rax test ecx, bufflen ;check if all the bytes in the buffer have been used jnz copy ;if so, jump to copy the remaining bytes not read into the buffer yet close: mov rdi, r15 ;move fd into rdi mov eax, 3 ;sys_close syscall jmp nextarg stdin: xor edi, edi ;stdin == 0 call read test eax,eax ;Check if the return value was 0 je exit ;Jump to exit on EOF recieved mov edi, 1 ;file descriptor = stdout mov edx, eax ;move num bytes read to number of bytes to write call write jmp stdin ; read function, takes rdi as an argument (a fd) read: mov edx, bufflen ;read up to bufflen bytes at once mov rsi, Buff ;Address of buffer to read into xor eax, eax ;sys_read syscall ret ; write function, takes rdi as an argument (a fd) and also rdx (number of bytes) write: mov rsi, Buff ;mov address of buffer mov eax, 1 ;sys_write syscall ret exit: xor edi, edi ; exit status == 0 mov eax, 60 ; SYSCALL number for EXIT syscall