-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmain.asm
178 lines (144 loc) · 3.95 KB
/
main.asm
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
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
; readfile -- Program display file contents on the screen.
; Arguments:
; 1) file path (mandatory)
; 2) number of lines (optional)
; If you don't provide second argument - whole file will be displayed
; Usage:
; ./readfile simple.txt
; ./readfile simple.txt 10
; ----------------------------------------------------------------------
section .data
; -----
; Constants
NULL equ 0 ; string termination
SYS_exit equ 60 ; return to OS
EXIT_SUCCESS equ 0 ; success code
LF equ 10 ; new line
; -----
; Error Codes
ENOENT equ -2 ; No such file or directory
EACCES equ -13 ; Permission denied
EISDIR equ -21 ; Argument is a directory
; -----
; Messages
separator db ": ", NULL
usage db "readfile quick help.", LF
db "If you need to display first-n lines from file specify second argument", LF
db "Usage: ./readfile simple.txt [n-lines]", LF, NULL
notFound db "File not found.", LF, NULL
negativeError db "ERROR: argument cannot be negative", LF, NULL
InvalidError db "ERROR: line number is invalid.", LF, NULL
NoAccessError db "Permission denied.", LF, NULL
IsDirError db "Is a directory.", LF, NULL
OtherError db "Unknown error.", LF, NULL
section .bss
fd resq 1 ; file descriptor
extern prints ; print string on screen
extern openFile ; file open
extern closeFile ; file close
extern s2int ; string to integer
extern readLines ; read lines from file
section .text
global main
main:
; Commandline args
mov r12, rdi ; argc
mov r13, rsi ; *argv[]
cmp r12, 2 ; if (argc < 2)
jl HelpMessage ; display help message and quit
; Open a file
mov rdi, qword [r13+1*8] ; argv[1] -- filepath
call openFile
; Check if file exists
cmp rax, ENOENT
je FileNotFound
; Check file permissions
cmp rax, EACCES
je NoAccess
; Handle other errors
cmp rax, 0
jb UnknownErr
; Save file descriptor
mov qword [fd], rax
; Check if number of lines was provided
cmp r12, 2
ja OptionalArg
; Read whole file
; -1 is a magick arg, that tells function to read whole file
mov rdi, qword [fd]
mov rsi, -1
call readLines
; ISDIR exception
cmp rax, EISDIR
je IsDir
jmp last
OptionalArg:
; convert second argument to integer
mov rdi, qword [r13+2*8]
call s2int
; Errors handled:
; * lines count cannot be negative
; * lines count cannot start with 0
; * lines count must contain only numbers
cmp rax, -1
je NegativeArg
cmp rax, -2
je InvalidNumber
; Read lines from file
mov rdi, qword [fd]
mov rsi, rax
call readLines
; ISDIR exception
cmp rax, EISDIR
je IsDir
; Close a file
mov rdi, qword [fd]
call closeFile
jmp last
; ----------------------------------------------
; ERROR handling
NegativeArg:
mov rdi, negativeError
call prints
jmp last
InvalidNumber:
mov rdi, InvalidError
call prints
jmp last
FileNotFound:
mov rdi, qword [r13+1*8]
call prints
mov rdi, separator
call prints
mov rdi, notFound
call prints
jmp last
NoAccess:
mov rdi, qword [r13+1*8]
call prints
mov rdi, separator
call prints
mov rdi, NoAccessError
call prints
jmp last
IsDir:
mov rdi, qword [r13+1*8]
call prints
mov rdi, separator
call prints
mov rdi, IsDirError
call prints
jmp last
UnknownErr:
mov rdi, OtherError
call prints
jmp last
HelpMessage:
mov rdi, usage
call prints
; -----
; Program end
last:
mov rax, SYS_exit
mov rdi, EXIT_SUCCESS
syscall