-
Notifications
You must be signed in to change notification settings - Fork 0
/
io.inc
224 lines (203 loc) · 3.17 KB
/
io.inc
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
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
%define BUFFER_SIZE 32
section .data
char_diff: db 0x00
buf : times 256 db 0
section .text
; %rdi - address of string
; OUT:
; %rax - length of string
string_length:
xor rax, rax
.loop:
cmp byte[rdi + rax], 0
je .exit
inc rax
jmp .loop
.exit:
ret
; %rdi - address of string
print_string:
call string_length
mov rsi, rdi
mov rdi, 1
mov rdx, rax
mov rax, 1
syscall
ret
; %rdi - code of character to print
print_char:
push rdi
mov rsi, rsp
mov rdi, 1
mov rdx, 1
mov rax, 1
syscall
pop rdi
ret
print_newline:
mov rdi, 10
jmp print_char
; %rdi - address of string
; %rsi - address of new string
string_copy:
call string_length
mov rcx, rax
inc rcx
xchg rsi, rdi
mov byte[rdi + rax], 0
rep movsb
ret
; %rdi - unsigned number to print
print_uint:
push rbp ; Save %rbp
mov rbp, rsp
mov rax, rdi
mov rdi, 10
sub rsp, BUFFER_SIZE
dec rbp
mov byte[rbp], 0
.loop:
dec rbp
xor rdx, rdx
div rdi
add rdx, '0'
mov byte[rbp], dl
test rax, rax
jnz .loop
mov rdi, rbp
call print_string
add rsp, BUFFER_SIZE
pop rbp
ret
; %rdi - signed number to print
print_int:
test rdi, rdi
jns .unsigned
push rdi
mov rdi, '-'
call print_char
pop rdi
neg rdi
.unsigned:
jmp print_uint
; %rdi - address of the first string
; %rsi - address of the second string
string_equals:
call string_length
mov rcx, rax
xchg rdi, rsi
call string_length
cmp rax, rcx
jne .not_equals
repe cmpsb
jne .not_equals
mov rax, 1
ret
.not_equals:
mov rax, 0
ret
read_char:
push 0
mov rsi, rsp
mov rdx, 1
xor rdi, rdi
xor rax, rax
syscall
pop rax
ret
read_word:
push r14
push r15
xor r14, r14
mov r15, rsi
dec r15
.read_first:
push rdi
call read_char
pop rdi
cmp al, ' '
je .read_first
cmp al, 10
je .read_first
cmp al, 13
je .read_first
cmp al, 9
je .read_first
test al, al
jz .read_success
.read_next:
mov byte [rdi + r14], al
inc r14
push rdi
call read_char
pop rdi
cmp al, ' '
je .read_success
cmp al, 10
je .read_success
cmp al, 13
je .read_success
cmp al, 9
je .read_success
test al, al
jz .read_success
cmp r14, r15
je .read_err
jmp .read_next
.read_success:
mov byte [rdi + r14], 0
mov rax, rdi
mov rdx, r14
pop r15
pop r14
ret
.read_err:
xor rax, rax
xor rdx, rdx
pop r15
pop r14
ret
; %rdi - address of the unsigned number string
; OUT:
; %rax - parsed unsigned number
; %rdx - amount of read digits
parse_uint:
call string_length
mov rcx, rax
mov rsi, rdi
xor rdx, rdx
xor rax, rax
.pars:
xor rdi, rdi
mov dil, byte[rsi + rdx]
cmp dil, '0'
jb .exit
cmp dil, '9'
ja .exit
sub dil, '0'
imul rax, 10
add rax, rdi
inc rdx
dec rcx
jnz .pars
.exit:
ret
; %rdi - address of the unsigned number string
; OUT:
; %rax - parsed signed number
; %rdx - amount of read digits (with '-')
parse_int:
cmp byte[rdi], '-'
je .minus
jmp parse_uint
.minus:
inc rdi ; Skip '-'
call parse_uint
test rdx, rdx
jz .null
neg rax
inc rdx
ret
.null:
xor eax, eax
ret