aboutsummaryrefslogtreecommitdiff
path: root/strutils.asm
blob: 22640f7c26b4901a56423669dedc89eef6753a17 (plain)
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
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;;  name: jaspos_strutils_strlen
;;  @param	string	string to measure
;;  @return	length	length of string
;;  Counts length of string at DS:arg1 and leaves
;;  SI as a pointer to the end of the string
;;
jaspos_strutils_strlen:
	pop		bp
	pop		si
	push	bp
	push	cx
	xor		cx, cx
.loop:
	lodsb
	cmp		al, 0
	jz		.quit
	inc		cx
	jmp		.loop
.quit:
	dec		ax
	dec		si
	mov		ax, cx
	pop		cx
	ret
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;;  name: jaspos_strutils_hex2str
;;  @param	buffer	buffer to write string to
;;  @param	number	hex integer to convert
;;  @return	none
;;  Converts hex word to string
;;
jaspos_strutils_hex2str:
	pop		bp							;
	pop		ax							;
	pop		di							;
	push	bp							;
	mov		bx, strutils_HexLookup		;
	std									; RW memory from right to left
	mov		cx, 2
.loop:
	push	ax
	shl		al, 4
	shr		al, 4
	xlatb
	stosb
	pop		ax
	shr		al, 4
	xlatb
	stosb
	xchg	ah, al
	loop	.loop

	cld									; RW memory from left to right
	ret
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;;  name: jaspos_strutils_d2str
;;  @param	buffer	buffer to write string to
;;  @param	number	fixed decimal to convert
;;  @return	none
;;  Converts integer word to string
;;
jaspos_strutils_d2str:
	std									; We're going to be STOSBing from right-to-left. Set the direction flag
	pop		bp							; Pop return address off the stack
	pop		dx							; Pop arg2 off - decimal number
	pop		di							; pop arg1 off - string buffer
	push	bp							; Push return address onto stack, ready for RET
	mov 	cx, 0x5						; Length of buffer
.loop:
	mov 	ax, dx						; Load remainder or inital number into AX
	xor		dx, dx
	mov 	bx, 10d						; We will divide by 10
	div 	bx							; Divide by DX (10)
	xchg 	dx, ax						; Save quotient in DL
	or	 	al, 00110000b				; Convert quotient into its ASCII equivalent (effectively add 0x30)
	stosb								; Store the converted digit in the buffer
	loop	.loop						; Loop until CX=0 i.e. when at end of string buffer
	cld									; Clear the direction flag; most things expect left-to-right
	ret
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;;  name: jaspos_strutils_compare
;;  @param	str1	one of the strings to compare
;;  @param	str2	the other string to compare
;;  @return	equal	zero flag set if equal, cleared if inequal
;;  Compares the string at DS:SI with ES:DI
;;
jaspos_strutils_compare:
	pop		bp							; Save the return address from being destroyed
	pop		si							; Load pointer to string 1 into SI
	pop		di							; Load pointer to string 2 into DI
	push	bp							; Put the return address back onto stack ready for RET
.loop:
	xchg	si, di						; Switch DI to be the pointer for now
	lodsb								; Load a byte from string 2
	mov		bl, al						; Move the loaded byte into BX so we can load a byte from the other string
	xchg	si, di						; Switch the registers back so we're loading from the other string next
	lodsb								; Load a byte from string 1

	cmp		al, bl						; Comapre the two bytes from each string
	jne		.inequal					; If not equal, jump accordingly to clear the zero flag and return

	cmp		al, 0						; If end of string, quit
	je		.equal

	cmp		bl, 0						; If end of string, quit
	je		.equal
	jmp		.loop

.equal:
	xor		ax, ax						; Zero-out AX to indicate equality
	cmp		ax, ax						; Set the zero flag too
	ret
.inequal:
	mov		ax, 1						; Set AX to 1 to indicate difference
	cmp		ax, 2						; And compare it with something it isn't to clear the zero flag
	ret
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;;  name: jaspos_strutils_tolower
;;  @param	str1	string to convert
;;  @return
;;  Converts the string at DS:arg1 to have all
;;  lowercase letters. Any non-uppercase letter
;;  is skipped over
;;
jaspos_strutils_tolower:
	pop		bp							; Pop return addresss
	pop		si							; Pop string pointer
	push	bp							; Push return address
	push	di							; Save DI
	mov		di, si						; Make sure we're writing the converted chars to the string
.loop:
	lodsb								; Load next byte from string
	cmp		al, 0						; Are we at the end of the string?
	je		.quit						; If so, exit the loop
	cmp		al, 'A'						; Is the character below 'A'?
	jl		.notchar					; If so, it's not an uppercase char
	cmp		al, 'Z'						; Is the char above 'Z'?
	jg		.notchar					; If so, it's not an uppercase char
	or		al, 00100000b				; Set bit 5 of the byte, thus adding 32 to it, converting it to lowercase
.notchar:
	stosb								; Store the byte
	jmp		.loop						; Do it all over again
.quit:
	pop		di
	ret
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;;  name: jaspos_strutils_toupper
;;  @param	str1	string to convert
;;  @return
;;  Converts the string at DS:arg1 to have all
;;  uppercase letters. Any non-lowercase letter
;;  is skipped over
;;
jaspos_strutils_toupper:
	pop		bp							;
	pop		si
	push	bp
	push	di							; Save DI
	push	ax
	mov		di, si						; Ensure we're writing converted chars into the string
.loop:
	lodsb
	cmp		al, 0						; End of string?
	je		.quit						; If so, quit
	cmp		al, 'a'						; Is the character below 'a'?
	jl		.notchar					; If so, it's not a lowercase char
	cmp		al, 'z'						; Is it above 'z'?
	jg		.notchar					; If so, it's not a lowercase char
	and		al, 11011111b				; Make bit 5 low, thus subtracting 32 from it, making it a lowercase char
.notchar:
	stosb								; Store the byte
	jmp		.loop						; Do it all over again with the next char
.quit:
	pop		ax
	pop		di
	ret
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;;  name: jaspos_strutils_trimleading
;;  @param	str1	string to convert
;;  @return
;;  Cuts leading spaces off a string
;;
jaspos_strutils_trimleading:
	pop		bp
	pop		si
	push	bp
	push	di
	mov		di, si
	push	si							; Push pointer to string
	call	jaspos_strutils_strlen		; Get string's length
	mov		cx, ax						; Ready CX with string length

	mov		si, di						; Put the original pointer back into SI
	push	cx							; Save the string length
.findloop:	; We need to find where the leading spaces stop
	lodsb								; Load next byte in string
	cmp		al, ' '						; Is it a space?
	jnz		.quitloop					; If not, quit
	loop	.findloop					; Otherwise, keep searching until we're at the end of the string
.quitloop:
	pop		cx							; Get our original string length back
	dec		si							; Currently SI points to the character after the last leading space, rectify
	inc		cx							; Because we DEC'd SI, we'll need to INC CX
	rep		movsb						; SI = where spaces end, DI = Raw beginning of string

	pop		di							;
	ret
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;;  name: jaspos_strutils_trimtrailing
;;  @param	str1	string to convert
;;  @return
;;  Moves null-terminator to cut trailing spaces
;;  off a string
;;
jaspos_strutils_trimtrailing:
	pop		bp
	pop		si
	push	bp
	push	di

	push	si
	call	jaspos_strutils_strlen
	mov		cx, ax

	std
	dec		si
.findloop:
	lodsb
	cmp		al, ' '
	jz		.findloop
	cld

	add		si, 2

	mov		di, si
	xor		ax, ax
	stosb

	pop		di
	ret
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;;  name: jaspos_strutils_instr
;;  @param	str1	string to find
;;  @param	str2	string to search in
;;  @return	instr	1 if str2 contains str2, else 0
;;  Searches str2 for an occurence of str1
;;
jaspos_strutils_instr:
	pop		bp
	pop		si			; SI = str2
	pop		di			; DI = str1
	push	bp
	push	cx
	push	dx
	mov		cx, si
	mov		dx, di

.loop:
	xchg	si, di
	lodsb				; Load a byte from str1
	cmp		al, 0		; Is the byte an end-of-string in the string to match?
	jz		.match		; If so, we've just found the string! Let's exit appropriately
	mov		bl, al		; Save it in bl

	xchg	si, di
	lodsb				; Load next byte from str2
	cmp		al, 0		; Is the byte an end-of-string?
	jz		.nomatch	; If so, exit with no match
	cmp		al, bl		; Are the bytes equal?

	jz		.loop
	inc		cx
	mov		si, cx
	mov		di, dx
	jmp		.loop

.match:
	pop		dx
	pop		cx
	mov		ax, 1
	ret

.nomatch:
	pop		dx
	pop		cx
	xor		ax, ax
	ret
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;;  name: jaspos_strutils_trim
;;  @param	string	string to trim
;;  @return	none
;;  Trims both trailing and leading spaces from
;;  string
;;
jaspos_strutils_trim:
	pop		bp
	pop		ax
	push	bp
	push	ax
	push	ax
	call	jaspos_strutils_trimleading
	pop		ax
	push	ax
	call	jaspos_strutils_trimtrailing
	ret
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;