1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
|
; 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
|