forked from nemasu/asmttpd
-
Notifications
You must be signed in to change notification settings - Fork 0
/
string.asm
326 lines (265 loc) · 6.47 KB
/
string.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
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
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
;asmttpd - Web server for Linux written in amd64 assembly.
;Copyright (C) 2014 Nathan Torchia <[email protected]>
;
;This file is part of asmttpd.
;
;asmttpd is free software: you can redistribute it and/or modify
;it under the terms of the GNU General Public License as published by
;the Free Software Foundation, either version 2 of the License, or
;(at your option) any later version.
;
;asmttpd is distributed in the hope that it will be useful,
;but WITHOUT ANY WARRANTY; without even the implied warranty of
;MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;GNU General Public License for more details.
;
;You should have received a copy of the GNU General Public License
;along with asmttpd. If not, see <http://www.gnu.org/licenses/>.
string_itoa:; rdi - buffer, rsi - int
stackpush
push rcx
push rbx
xchg rdi, rsi
call get_number_of_digits
xchg rdi, rsi
mov rcx, rax ;
;add null
mov al, 0x0
mov [rdi+rcx], al
dec rcx
mov rax, rsi ; value to print
xor rdx, rdx ; zero other half
mov rbx, 10
string_itoa_start:
xor rdx, rdx ; zero other half
div rbx ; divide by 10
add rdx, 0x30
mov [rdi+rcx], dl
dec rcx
cmp rax, 9
ja string_itoa_start
cmp rcx, 0
jl string_itoa_done
add rax, 0x30 ;last digit
mov [rdi+rcx], al
string_itoa_done:
pop rbx
pop rcx
stackpop
ret
string_atoi: ; rdi = string, rax = int
stackpush
mov r8, 0 ; ;return
call get_string_length
mov r10, rax ; length
cmp rax, 0
je string_atoi_ret_empty
mov r9, 1 ; multiplier
dec r10
string_atoi_loop:
xor rbx, rbx
mov bl, BYTE [rdi+r10]
sub bl, 0x30 ;get byte, subtract to get real from ascii value
mov rax, r9
mul rbx ; multiply value by multiplier
add r8, rax ; add result to running total
dec r10 ; next digit
mov rax, 10 ; multiply r9 ( multiplier ) by 10
mul r9
mov r9, rax
cmp r10, -1
jne string_atoi_loop
jmp string_atoi_ret
string_atoi_ret_empty:
mov rax, -1
stackpop
ret
string_atoi_ret:
mov rax, r8
stackpop
ret
string_copy: ; rdi = dest, rsi = source, rdx = bytes to copy
stackpush
mov rcx, rdx
inc rcx ; to get null
cld
rep movsb
stackpop
ret
string_concat_int: ;rdi = string being added to, rsi = int to add, ret: new length
stackpush
call get_string_length
add rdi, rax
call string_itoa
call get_string_length
stackpop
ret
string_concat: ;rdi = string being added to, rsi = string to add, ret: new length
stackpush
call get_string_length
add rdi, rax ; Go to end of string
mov r10, rax
;Get length of source ie. bytes to copy
push rdi
mov rdi, rsi
call get_string_length
inc rax ; null
mov rcx, rax
add r10, rax
pop rdi
rep movsb
mov rax, r10
stackpop
ret
string_contains: ;rdi = haystack, rsi = needle, ret = rax: location of string, else -1
stackpush
xor r10, r10 ; total length from beginning
xor r8, r8 ; count from offset
string_contains_start:
mov dl, BYTE [rdi]
cmp dl, 0x00
je string_contains_ret_no
cmp dl, BYTE [rsi]
je string_contains_check
inc rdi
inc r10 ; count from base ( total will be r10 + r8 )
jmp string_contains_start
string_contains_check:
inc r8 ; already checked at pos 0
cmp BYTE [rsi+r8], 0x00
je string_contains_ret_ok
mov dl, [rdi+r8]
cmp dl ,0x00
je string_contains_ret_no
cmp dl, [rsi+r8]
je string_contains_check
inc rdi
inc r10
jmp string_contains_start
string_contains_ret_ok:
mov rax, r10
jmp string_contains_ret
string_contains_ret_no:
mov rax, -1
string_contains_ret:
stackpop
ret
;Removes first instance of string
string_remove: ;rdi = source, rsi = string to remove, ret = 1 for removed, 0 for not found
stackpush
mov r9, 0 ; return flag
call get_string_length
mov r8, rax ; r8: source length
cmp r8, 0
mov rax, 0
jle string_remove_ret ; source string empty?
push rdi
mov rdi, rsi
call get_string_length
mov r10, rax ; r10: string to remove length
pop rdi
cmp r10, 0
mov rax, 0
jle string_remove_ret ; string to remove is blank?
string_remove_start:
call string_contains
cmp rax,-1
je string_remove_ret
;Shift source string over
add rdi, rax
mov rsi, rdi
add rsi, r10 ; copying to itself sans found string
cld
string_remove_do_copy:
lodsb
stosb
cmp al, 0x00
jne string_remove_do_copy
mov r9, 1
string_remove_ret:
mov rax, r9
stackpop
ret
string_ends_with:;rdi = haystack, rsi = needle, ret = rax: 0 false, 1 true
stackpush
;Get length of haystack, store in r8
call get_string_length
mov r8, rax
;Get length of needle, store in r10
push rdi
mov rdi, rsi
call get_string_length
mov r10, rax
pop rdi
add rdi, r8
add rsi, r10
xor rax, rax
xor rdx, rdx
string_ends_with_loop:
;Start from end, dec r10 till 0
mov dl, BYTE [rdi]
cmp dl, BYTE [rsi]
jne string_ends_with_ret
dec rdi
dec rsi
dec r10
cmp r10, 0
jne string_ends_with_loop
mov rax, 1
string_ends_with_ret:
stackpop
ret
string_char_at_reverse: ;rdi = haystack, rsi = count from end, rdx = character(not pointer), ret = rax: 0 false, 1 true
stackpush
inc rsi ; include null
call get_string_length
add rdi, rax ; go to end
sub rdi, rsi ; subtract count
mov rax, 0 ; set return to false
cmp dl, BYTE [rdi] ; compare rdx(dl)
jne string_char_at_reverse_ret
mov rax, 1
string_char_at_reverse_ret:
stackpop
ret
print_line: ; rdi = pointer, rsi = length
stackpush
call sys_write
mov rdi, new_line
mov rsi, 1
call sys_write
stackpop
ret
get_string_length: ; rdi = pointer, ret rax
stackpush
cld
mov r10, -1
mov rsi, rdi
get_string_length_start:
inc r10
lodsb
cmp al, 0x00
jne get_string_length_start
mov rax, r10
stackpop
ret
get_number_of_digits: ; of rdi, ret rax
stackpush
push rbx
push rcx
mov rax, rdi
mov rbx, 10
mov rcx, 1 ;count
gnod_cont:
cmp rax, 10
jb gnod_ret
xor rdx,rdx
div rbx
inc rcx
jmp gnod_cont
gnod_ret:
mov rax, rcx
pop rcx
pop rbx
stackpop
ret