source: xtideuniversalbios/trunk/Configurator/Src/Libraries/string.asm@ 76

Last change on this file since 76 was 75, checked in by Tomi Tilli, 14 years ago

Changes to old Configurator:

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