source: xtideuniversalbios/trunk/XTIDE_Universal_BIOS/Src/Libraries/string.asm@ 38

Last change on this file since 38 was 3, checked in by Tomi Tilli, 15 years ago
File size: 18.6 KB
Line 
1; File name : string.asm
2; Project name : String library
3; Created date : 7.10.2009
4; Last update : 26.11.2009
5; Author : Tomi Tilli
6; Description : ASM library to work as Standard C String and Character.
7
8;--------------- Equates -----------------------------
9
10; String library function to include
11;%define USE_STR_ISCHAR
12;%define USE_STR_ISBASECHAR
13;%define USE_STR_BUFFHASCHAR
14;%define USE_STR_BUFFCMP
15;%define USE_STR_TOUINT
16;%define USE_STR_LEN
17;%define USE_STR_TOKEN
18;%define USE_STR_WITHIN
19;%define USE_STR_TOLOWER
20;%define USE_STR_TOUPPER
21
22; Special characters for strings
23STOP EQU 0 ; String ending character
24BELL EQU 7 ; Bell
25BS EQU 8 ; Backspace
26TAB EQU 9 ; Horizontal tab
27LF EQU 10 ; Line feed \ Combine to...
28CR EQU 13 ; Carriage return / ...get a newline
29ESC EQU 27 ; ESC
30
31; Misc characters
32UARROW EQU 24 ; Up arrow
33DARROW EQU 25 ; Down arrow
34RARROW EQU 26 ; Right arrow
35LARROW EQU 27 ; Left arrow
36
37; Characters for printing boxes
38B_V EQU 186 ; Bold vertical border (Y-axis)
39B_H EQU 205 ; Bold horizontal border (X-axis)
40B_TL EQU 201 ; Bold top left border
41B_TR EQU 187 ; Bold top right border
42B_LR EQU 188 ; Bold lower right border
43B_LL EQU 200 ; Bold lower left border
44
45T_V EQU 179 ; Thin vertical border (Y-axis)
46T_H EQU 196 ; Thin horizontal border (X-axis)
47T_TL EQU 218 ; Thin top left border
48T_TR EQU 191 ; Thin top right border
49T_LR EQU 217 ; Thin lower right border
50T_LL EQU 192 ; Thin lower left border
51
52BVL_THR EQU 199 ; Bold vert on left, Thin horiz on right (||-)
53THL_BVR EQU 182 ; Thin horiz on left, Bold vert on right (-||)
54TVL_BHR EQU 198 ; Thin vert on left, Bold horiz on right (|=)
55BHL_TVR EQU 181 ; Bold horiz on left, Thin vert on right (=|)
56
57; Blocks
58MIN_BLCK EQU 176 ; Few character pixels set
59FULL_BLCK EQU 219 ; All character pixels set
60
61
62;-------------- Private global variables -------------
63; Section containing initialized data
64;SECTION .data
65
66
67;-------------- Public functions ---------------------
68; Section containing code
69SECTION .text
70
71;--------------------------------------------------------------------
72; Checks if character is some type of character.
73;
74; String_IsAlphaNum (checks if alphanumeric letter, isalnum on C)
75; String_IsAlpha (checks if alphabetic letter, isalpha on C)
76; String_IsDigit (checks if decimal digit, isdigit on C)
77; String_IsLower (checks if lowercase letter, islower on C)
78; String_IsSpace (checks if any space character, isspace on C)
79; String_IsUpper (checks if uppercase letter, isupper on C)
80; String_IsHexDigit (checks if hexadecimal digit, isxdigit on C)
81; Parameters:
82; AL: Character to check
83; Returns:
84; CF: Set if character is the type to check
85; Cleared if character is not the type to check
86; Corrupts registers:
87; Nothing
88;--------------------------------------------------------------------
89%ifdef USE_STR_ISCHAR
90ALIGN JUMP_ALIGN
91String_IsAlphaNum:
92 call String_IsAlpha ; Is alphabetic letter?
93 jnc .CheckDigit ; If not, jump to check if digit
94 ret
95.CheckDigit:
96 call String_IsDigit ; Is dec digit?
97 ret
98
99ALIGN JUMP_ALIGN
100String_IsAlpha:
101 call String_IsLower ; Is lower case letter?
102 jnc .CheckUpper ; If not, jump to check if upper
103 ret
104.CheckUpper:
105 call String_IsUpper ; Is upper case letter?
106 ret
107
108ALIGN JUMP_ALIGN
109String_IsDigit:
110 cmp al, '0' ; At least first dec digit?
111 jb _String_IsRetFalse ; If not, return FALSE
112 cmp al, '9'+1 ; At most last dec digit?
113 ret
114
115ALIGN JUMP_ALIGN
116String_IsLower:
117 cmp al, 'a' ; At least first lower case letter?
118 jb _String_IsRetFalse ; If not, return FALSE
119 cmp al, 'z'+1 ; At most last lower case letter?
120 ret
121
122ALIGN JUMP_ALIGN
123String_IsSpace:
124 cmp al, ' '+1 ; Space or non-visible character?
125 ret
126
127ALIGN JUMP_ALIGN
128String_IsUpper:
129 cmp al, 'A' ; At least first upper case letter?
130 jb _String_IsRetFalse ; If not, return FALSE
131 cmp al, 'Z'+1 ; At most last upper case letter?
132 ret
133
134ALIGN JUMP_ALIGN
135String_IsHexDigit:
136 call String_IsAlphaNum ; Is alphabetic letter or digit?
137 jc .CheckHex ; If so, jump to check A...F
138 ret
139.CheckHex:
140 push ax ; Store character
141 call String_ToLower ; Convert to lower case letter
142 cmp al, 'f'+1 ; Last valid hex alphanumeric?
143 pop ax ; Restore character
144 ret
145
146ALIGN JUMP_ALIGN
147_String_IsRetFalse:
148 clc ; Clear CF since false
149 ret
150%endif ; USE_STR_ISCHAR
151
152
153;--------------------------------------------------------------------
154; Checks if character belongs to specified numeric base.
155;
156; String_IsBaseChar
157; Parameters:
158; AL: Character to check
159; CL: Numeric base (10=dec, 16=hex etc.)
160; Returns:
161; AH: Integer value for character
162; CF: Set if character belongs to base
163; Set if character does not belong to base
164; Corrupts registers:
165; Nothing
166;--------------------------------------------------------------------
167%ifdef USE_STR_ISBASECHAR
168ALIGN JUMP_ALIGN
169String_IsBaseChar:
170 mov ah, al ; Copy char to AH
171 call String_IsDigit ; Is '0'...'9'?
172 jc .ConvertDigit ; If so, jump to convert
173 call String_IsAlpha ; Is alphabetic letter?
174 jnc .RetFalse ; If not, return FALSE
175 call String_ToLower ; Convert to lower case
176 xchg al, ah ; Converted char to AH
177 sub ah, 'a'-10 ; From char to integer: a=10, b=11...
178 cmp ah, cl ; Belongs to base?
179 jae .RetFalse ; If not, return FALSE
180 stc ; Set CF since belongs to base
181 ret
182ALIGN JUMP_ALIGN
183.ConvertDigit:
184 sub ah, '0' ; Convert char to integer
185 cmp ah, cl ; Belongs to base?
186 jae .RetFalse ; If not, return FALSE
187 stc ; Set CF since belongs to base
188 ret
189ALIGN JUMP_ALIGN
190.RetFalse:
191 clc ; Clear CF since char doesn't belong to b
192 ret
193%endif
194
195
196;--------------------------------------------------------------------
197; Finds first occurrence of character from buffer (memchr on C).
198;
199; String_BuffHasChar
200; Parameters:
201; AL: Character to check
202; CX: Buffer length in bytes (1...65535, 0 clears CF)
203; ES:DI: Pointer to buffer
204; Returns:
205; AX: Index of character in buffer (if char found)
206; ES:BX: Pointer to character location (if char found)
207; CF: Set if character found
208; Cleared if character not found
209; Corrupts registers:
210; Nothing
211;--------------------------------------------------------------------
212%ifdef USE_STR_BUFFHASCHAR
213ALIGN JUMP_ALIGN
214String_BuffHasChar:
215 jcxz .Return ; Check length so no need to initialise ZF
216 push di ; Store offset to buffer
217times 2 push cx ; Store CX
218 cld ; Set SCASB to increment DI
219 repne scasb ; Compare bytes to AL until found or CX=0
220 jne .CharNotFound ; Character not found, return FALSE
221
222 ; Character found
223 pop ax ; Pop buffer length
224 sub ax, cx ; Subtract number of chars left
225 dec ax ; Number of chars scanned to found index
226 lea bx, [di-1] ; Load character offset to BX
227 pop cx ; Restore CX
228 pop di ; Restore DI
229 stc ; Set CF since char found
230 ret
231.CharNotFound:
232times 2 pop cx ; Restore CX
233 pop di ; Restore DI
234.Return:
235 clc ; Clear CF since char not found
236 ret
237%endif
238
239
240;--------------------------------------------------------------------
241; Compares two buffers (memcmp on C).
242;
243; String_BuffCmp
244; Parameters:
245; CX: Buffer length in bytes (1...65535, 0 clears ZF)
246; DS:SI: Pointer to buffer 1
247; ES:DI: Pointer to buffer 2
248; Returns:
249; AX: Index of unequal character (if buffers are not equal)
250; ZF: Set if buffers are equal
251; Cleared if buffers are not equal
252; Corrupts registers:
253; Nothing
254;--------------------------------------------------------------------
255%ifdef USE_STR_BUFFCMP
256ALIGN JUMP_ALIGN
257String_BuffCmp:
258 jcxz .ReturnUnequal ; Check length so no need to initialise ZF
259 push di ; Store offset to buffer 2
260 push si ; Store offset to buffer 1
261times 2 push cx ; Store CX
262 cld ; Set CMPSB to increment SI and DI
263 repe cmpsb ; Compare bytes until not equal or CX=0
264 jne .BuffersUnequal ; Unequal byte found, return FALSE
265 times 2 pop cx ; Restore CX
266 pop si ; Restore SI
267 pop di ; Restore DI
268 ret
269.BuffersUnequal:
270 pop ax ; Pop buffer length
271 sub ax, cx ; Subtrack number of chars left
272 dec ax ; Number of chars compared to unequal idx
273 xor cx, cx ; Zero CX
274 dec cx ; ZF=0
275 pop cx ; Restore CX
276 pop si ; Restore SI
277 pop di ; Restore DI
278 ret
279.ReturnUnequal:
280 xor ax, ax ; Zero AX
281 dec ax ; AX = FFFFh, ZF=0
282 ret
283%endif
284
285
286;--------------------------------------------------------------------
287; Converts a string buffer to unsigned 32-bit integer.
288;
289; String_BuffToUInt
290; Parameters:
291; ES:DI: Pointer to string buffer to convert
292; CX: Base (10=dec, 16=hex etc.)
293; SI: Buffer length in characters
294; Returns:
295; DX:AX: 32-bit unsigned integer
296; CF: Set if converted successfully
297; Cleared if error
298; Corrupts registers:
299; Nothing
300;--------------------------------------------------------------------
301%ifdef USE_STR_TOUINT
302ALIGN JUMP_ALIGN
303String_BuffToUInt:
304 ; Copy ES:DI to DS:SI
305 push ds ; Store DS
306 push si ; Store SI
307 push di ; Store DI
308 push bx ; Store BX
309 xchg si, di ; Offset to SI, lenght to DI
310 push es
311 pop ds
312
313 ; Prepare to read chars
314 xor dx, dx ; Zero DX (HIWORD)
315 xor bx, bx ; Zero BX (LOWORD)
316ALIGN JUMP_ALIGN
317.CharLoop:
318 lodsb ; Load char to AL
319 call String_IsBaseChar ; Is valid character? (AH=digit)
320 jnc .RetFalse ; If not, return FALSE
321 xchg ax, bx ; AX=LOWORD, BX=digit and char
322 call Math_MulDWbyW ; DX:AX *= CX
323 xchg ax, bx ; AX=digit and char, BX=LOWORD
324 mov al, ah ; Copy digit to AL
325 xor ah, ah ; Zero AH, AX=digit
326 add bx, ax ; Add digit to LOWORD
327 adc dx, 0 ; Add carry to HIWORD
328 dec di ; Decrement characters left
329 jnz .CharLoop ; Loop while characters left
330
331 mov ax, bx ; Copy loword to AX
332 pop bx ; Restore BX
333 pop di ; Restore DI
334 pop si ; Restore SI
335 pop ds ; Restore DS
336 stc ; Set CF since success
337 ret
338ALIGN JUMP_ALIGN
339.RetFalse:
340 mov ax, bx ; Copy (likely incomplete) loword to AX
341 pop bx ; Restore BX
342 pop di ; Restore DI
343 pop si ; Restore SI
344 pop ds ; Restore DS
345 clc ; Clear CF since error
346 ret
347%endif
348
349
350;--------------------------------------------------------------------
351; Returns string lenght. Strings must end to STOP character (strlen on C).
352;
353; String_StrLen
354; Parameters:
355; ES:DI: Pointer to string
356; Returns:
357; AX: String length in characters excluding STOP char
358; CF: Set if STOP character was found
359; Cleared if STOP character was not found
360; Corrupts registers:
361; Nothing
362;--------------------------------------------------------------------
363%ifdef USE_STR_LEN
364ALIGN JUMP_ALIGN
365String_StrLen:
366 push cx ; Store CX
367 mov al, STOP ; Load string end char to AL
368 mov cx, -1 ; Scan for maximum string length
369 call String_BuffHasChar ; Find offset for string ending char
370 pop cx ; Restore CX
371 ret
372%endif
373
374
375;--------------------------------------------------------------------
376; Returns length for token string. Token strings ends to any whitespace
377; character or to STOP.
378;
379; String_TokenLen
380; Parameters:
381; ES:DI: Pointer to token string
382; Returns:
383; AX: Token length in characters
384; Corrupts registers:
385; Nothing
386;--------------------------------------------------------------------
387%ifdef USE_STR_TOKEN
388ALIGN JUMP_ALIGN
389String_TokenLen:
390 push bx ; Store BX
391 xor bx, bx ; Zero BX for token length
392ALIGN JUMP_ALIGN
393.CharLoop:
394 mov al, [es:di+bx] ; Load character to AL
395 cmp al, STOP ; End of token?
396 je .Return ; If so, return
397 call String_IsSpace ; End of token?
398 jc .Return ; If so, return
399 inc bx ; Increment token length
400 jmp .CharLoop ; Loop while characters left
401ALIGN JUMP_ALIGN
402.Return:
403 mov ax, bx ; Copy string length to AX
404 pop bx ; Restore BX
405 ret
406%endif
407
408
409;--------------------------------------------------------------------
410; Returns index and ptr to first occurrence of
411; string 2 in string 1 (strstr on C).
412; Strings must be STOP terminated strings.
413;
414; String_StrWithin
415; Parameters:
416; DS:SI: Pointer to string 1
417; ES:DI: Pointer to string 2
418; Returns:
419; AX: Index to first occurrence of string 2 in string 1
420; DS:BX: Pointer to first occurrence of string 2 in string 1
421; CF: Set if string 2 was found in string 1
422; Cleared if string 2 was not found
423; Corrupts registers:
424; Nothing
425;--------------------------------------------------------------------
426%ifdef USE_STR_WITHIN
427ALIGN JUMP_ALIGN
428String_StrWithin:
429 push cx ; Store CX
430 push si ; Store SI
431 call String_StrLen ; Load str2 length to AX
432 mov cx, ax ; Copy str2 length to CX
433
434ALIGN JUMP_ALIGN
435.Str1CharLoop:
436 cmp BYTE [si], STOP ; End of string?
437 je .Str2NotFound ; If so, return FALSE
438 call String_BuffCmp ; str2 found in str1?
439 je .Str2Found ; If so, break loop
440 add si, ax ; Add index to first unmatching char
441 inc si ; Increment str1 ptr
442 jmp .Str1CharLoop ; Loop while characters left
443
444ALIGN JUMP_ALIGN
445.Str2Found:
446 mov bx, si ; Copy ptr to BX
447 mov ax, si ; Copy ptr to AX
448 pop si ; Restore SI
449 pop cx ; Restore CX
450 sub ax, si ; Calculate index to str2 in str1
451 stc ; Set CF since str2 found
452 ret
453ALIGN JUMP_ALIGN
454.Str2NotFound:
455 xor bx, bx ; Zero BX
456 pop si ; Restore SI
457 pop cx ; Restore CX
458 clc ; Clear CF since str2 was not found
459 ret
460%endif
461
462
463;--------------------------------------------------------------------
464; Returns pointer to wanted token inside STOP terminated string.
465; Tokens are separated by any white space characters.
466;
467; String_StrToken
468; Parameters:
469; CX: Index of token to return
470; ES:DI: Pointer to string
471; Returns:
472; AX: Token string length (if token found)
473; ES:DI: Pointer to token (if token found)
474; CF: Set if token found
475; Cleared if token not found
476; Corrupts registers:
477; Nothing
478;--------------------------------------------------------------------
479%ifdef USE_STR_TOKEN
480ALIGN JUMP_ALIGN
481String_StrToken:
482 push cx ; Store CX
483 push si ; Store SI
484 push ds ; Store DS
485 push es ; Copy ES:DI to DS:SI
486 pop ds
487 mov si, di
488 inc cx ; Increment to number of tokens to search
489 cld ; LODSB to increment SI
490ALIGN JUMP_ALIGN
491.ConsumeWhite:
492 lodsb ; Load char to AL from [DS:SI]
493 cmp al, STOP ; End of string?
494 je .NotFound ; If so, token was not found
495 call String_IsSpace ; Any whitespace character?
496 jc .ConsumeWhite ; If so, skip it
497 dec si ; Decrement SI to point first non-space
498 mov di, si ; Copy offset to token to DI
499ALIGN JUMP_ALIGN
500.TokenLoop:
501 lodsb ; Load char to AL
502 cmp al, STOP ; End of string?
503 je .EndOfString ; If so, end token
504 call String_IsSpace ; Any whitespace character?
505 jnc .TokenLoop ; If not, loop
506 loop .ConsumeWhite ; Loop until wanted token found
507.RetToken:
508 pop ds ; Restore DS
509 pop si ; Restore SI
510 pop cx ; Restore CX
511 call String_TokenLen ; Get token length to AX
512 stc ; Set CF since token found
513 ret
514ALIGN JUMP_ALIGN
515.EndOfString:
516 dec si ; Offset to STOP
517 cmp di, si ; STOP only char in token?
518 je .NotFound ; If so, then it is not valid token
519 loop .NotFound ; If last token was not wanted
520 jmp .RetToken
521ALIGN JUMP_ALIGN
522.NotFound:
523 pop ds ; Restore DS
524 pop si ; Restore SI
525 pop cx ; Restore CX
526 clc ; Clear CF since token not found
527 ret
528%endif
529
530
531;--------------------------------------------------------------------
532; Converts a STOP terminated string to unsigned 32-bit integer.
533;
534; String_StrToUInt
535; Parameters:
536; ES:DI: Pointer to string to convert
537; CX: Base (10=dec, 16=hex etc.)
538; Returns:
539; DX:AX: 32-bit unsigned integer
540; CF: Set if converted successfully
541; Cleared if error
542; Corrupts registers:
543; Nothing
544;--------------------------------------------------------------------
545%ifdef USE_STR_TOUINT
546ALIGN JUMP_ALIGN
547String_StrToUInt:
548 push si
549 call String_StrLen ; Get string length to AX
550 mov si, ax ; Copy length to SI
551 call String_BuffToUInt ; Convert to integer in DX:AX
552 pop si
553 ret
554%endif
555%if 0
556String_StrToUInt: ; Faster but we want to minimize size
557 ; Copy ES:DI to DS:SI
558 push ds ; Store DS
559 push si ; Store SI
560 push bx ; Store BX
561 mov si, di ; Copy ES:DI to DS:SI
562 push es
563 pop ds
564
565 ; Prepare to read chars
566 xor dx, dx ; Zero DX (HIWORD)
567 xor bx, bx ; Zero BX (LOWORD)
568ALIGN JUMP_ALIGN
569.CharLoop:
570 lodsb ; Load char to AL
571 cmp al, STOP ; End of string?
572 je .ConvComplete ; If so, break loop
573 call String_IsBaseChar ; Is valid character? (AH=digit)
574 jnc .RetFalse ; If not, return FALSE
575 xchg ax, bx ; AX=LOWORD, BX=digit and char
576 call Math_MulDWbyW ; DX:AX *= CX
577 xchg ax, bx ; AX=digit and char, BX=LOWORD
578 mov al, ah ; Copy digit to AL
579 xor ah, ah ; Zero AH, AX=digit
580 add bx, ax ; Add digit to LOWORD
581 adc dx, 0 ; Add carry to HIWORD
582 jmp .CharLoop ; Loop while valid characters
583ALIGN JUMP_ALIGN
584.ConvComplete:
585 mov ax, bx ; Copy loword to AX
586 pop bx ; Restore BX
587 pop si ; Restore SI
588 pop ds ; Restore DS
589 stc ; Set CF since success
590 ret
591ALIGN JUMP_ALIGN
592.RetFalse:
593 mov ax, bx ; Copy (likely incomplete) loword to AX
594 pop bx ; Restore BX
595 pop si ; Restore SI
596 pop ds ; Restore DS
597 clc ; Clear CF since error
598 ret
599%endif
600
601
602;--------------------------------------------------------------------
603; Converts upper case character to lower case character.
604;
605; String_ToLower
606; Parameters:
607; AL: Character to convert
608; Returns:
609; AL: Character with possible conversion
610; Corrupts registers:
611; Nothing
612;--------------------------------------------------------------------
613%ifdef USE_STR_TOLOWER
614ALIGN JUMP_ALIGN
615String_ToLower:
616 call String_IsUpper ; Is upper case character?
617 jnc .Return ; If not, return
618 add al, 'a'-'A' ; Convert to lower case
619.Return:
620 ret
621%endif
622
623
624;--------------------------------------------------------------------
625; Converts lower case character to upper case character.
626;
627; String_ToUpper
628; Parameters:
629; AL: Character to convert
630; Returns:
631; AL: Character with possible conversion
632; Corrupts registers:
633; Nothing
634;--------------------------------------------------------------------
635%ifdef USE_STR_TOUPPER
636ALIGN JUMP_ALIGN
637String_ToUpper:
638 call String_IsLower ; Is lower case character?
639 jnc .Return ; If not, return
640 sub al, 'a'-'A' ; Convert to upper case
641.Return:
642 ret
643%endif
Note: See TracBrowser for help on using the repository browser.