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

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

Changes to old configurator:

  • Optimizations by Krille
File size: 18.0 KB
Line 
1; File name : string.asm
2; Project name : String library
3; Created date : 7.10.2009
4; Last update : 4.1.2011
5; Author : Tomi Tilli,
6; : Krister Nordvall (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 jnc .ExitStrIsHexDigit ; If it is, check A...F. If not, exit
133 push ax ; Store character
134 call String_ToLower ; Convert to lower case letter
135 cmp al, 'f'+1 ; Last valid hex alphanumeric?
136 pop ax ; Restore character
137
138.ExitStrIsHexDigit:
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 jnc .CheckForAlpha ; If not, check for alphabetic letter
168 sub al, '0' ; Convert char to integer
169 jmp .FinalizeAXAndCheckBase
170
171.CheckForAlpha:
172 call String_IsAlpha ; Is alphabetic letter?
173 jnc .JustRet ; If not, return FALSE
174 call String_ToLower ; Convert to lower case
175 sub al, 'a'-10 ; From char to integer: a=10, b=11...
176
177.FinalizeAXAndCheckBase:
178 xchg al, ah ; Converted char to AH
179 cmp ah, cl ; Belongs to base?
180
181.JustRet: ; CF now reflects TRUE/FALSE so just return
182 ret
183%endif
184
185
186;--------------------------------------------------------------------
187; Finds first occurrence of character from buffer (memchr on C).
188;
189; String_BuffHasChar
190; Parameters:
191; AL: Character to check
192; CX: Buffer length in bytes (1...65535, 0 clears CF)
193; ES:DI: Pointer to buffer
194; Returns:
195; AX: Index of character in buffer (if char found)
196; ES:BX: Pointer to character location (if char found)
197; CF: Set if character found
198; Cleared if character not found
199; Corrupts registers:
200; Nothing
201;--------------------------------------------------------------------
202%ifdef USE_STR_BUFFHASCHAR
203ALIGN JUMP_ALIGN
204String_BuffHasChar:
205 jcxz .Return ; Check length so no need to initialise ZF
206 push di ; Store offset to buffer
207times 2 push cx ; Store CX
208 cld ; Set SCASB to increment DI
209 repne scasb ; Compare bytes to AL until found or CX=0
210 jne .CharNotFound ; Character not found, return FALSE
211
212 ; Character found
213 pop ax ; Pop buffer length
214 sub ax, cx ; Subtract number of chars left
215 dec ax ; Number of chars scanned to found index
216 lea bx, [di-1] ; Load character offset to BX
217 pop cx ; Restore CX
218 pop di ; Restore DI
219 stc ; Set CF since char found
220 ret
221.CharNotFound:
222times 2 pop cx ; Restore CX
223 pop di ; Restore DI
224.Return:
225 clc ; Clear CF since char not found
226 ret
227%endif
228
229
230;--------------------------------------------------------------------
231; Compares two buffers (memcmp on C).
232;
233; String_BuffCmp
234; Parameters:
235; CX: Buffer length in bytes (1...65535, 0 clears ZF)
236; DS:SI: Pointer to buffer 1
237; ES:DI: Pointer to buffer 2
238; Returns:
239; AX: Index of unequal character (if buffers are not equal)
240; ZF: Set if buffers are equal
241; Cleared if buffers are not equal
242; Corrupts registers:
243; Nothing
244;--------------------------------------------------------------------
245%ifdef USE_STR_BUFFCMP
246ALIGN JUMP_ALIGN
247String_BuffCmp:
248 jcxz .ReturnUnequal ; Check length so no need to initialise ZF
249 push di ; Store offset to buffer 2
250 push si ; Store offset to buffer 1
251times 2 push cx ; Store CX
252 cld ; Set CMPSB to increment SI and DI
253 repe cmpsb ; Compare bytes until not equal or CX=0
254 jne .BuffersUnequal ; Unequal byte found, return FALSE
255 times 2 pop cx ; Restore CX
256 pop si ; Restore SI
257 pop di ; Restore DI
258 ret
259.BuffersUnequal:
260 pop ax ; Pop buffer length
261 sub ax, cx ; Subtrack number of chars left
262 dec ax ; Number of chars compared to unequal idx
263 xor cx, cx ; Zero CX
264 dec cx ; ZF=0
265 pop cx ; Restore CX
266 pop si ; Restore SI
267 pop di ; Restore DI
268 ret
269.ReturnUnequal:
270 xor ax, ax ; Zero AX
271 dec ax ; AX = FFFFh, ZF=0
272 ret
273%endif
274
275
276;--------------------------------------------------------------------
277; Converts a string buffer to unsigned 32-bit integer.
278;
279; String_BuffToUInt
280; Parameters:
281; ES:DI: Pointer to string buffer to convert
282; CX: Base (10=dec, 16=hex etc.)
283; SI: Buffer length in characters
284; Returns:
285; DX:AX: 32-bit unsigned integer
286; CF: Set if converted successfully
287; Cleared if error
288; Corrupts registers:
289; Nothing
290;--------------------------------------------------------------------
291%ifdef USE_STR_TOUINT
292ALIGN JUMP_ALIGN
293String_BuffToUInt:
294 ; Copy ES:DI to DS:SI
295 push ds ; Store DS
296 push si ; Store SI
297 push di ; Store DI
298 push bx ; Store BX
299 xchg si, di ; Offset to SI, lenght to DI
300 push es
301 pop ds
302
303 ; Prepare to read chars
304 xor dx, dx ; Zero DX (HIWORD)
305 xor bx, bx ; Zero BX (LOWORD)
306ALIGN JUMP_ALIGN
307.CharLoop:
308 lodsb ; Load char to AL
309 call String_IsBaseChar ; Is valid character? (AH=digit)
310 jnc .RetFalse ; If not, return FALSE
311 xchg ax, bx ; AX=LOWORD, BX=digit and char
312 call Math_MulDWbyW ; DX:AX *= CX
313 xchg ax, bx ; AX=digit and char, BX=LOWORD
314 mov al, ah ; Copy digit to AL
315 xor ah, ah ; Zero AH, AX=digit
316 add bx, ax ; Add digit to LOWORD
317 adc dx, 0 ; Add carry to HIWORD
318 dec di ; Decrement characters left
319 jnz .CharLoop ; Loop while characters left
320
321 stc ; Set CF since success
322.RetFalse: ; If we jumped to here no CLC is needed to reflect a FALSE condition
323 mov ax, bx ; Copy loword to AX (may be incomplete)
324 pop bx ; Restore BX
325 pop di ; Restore DI
326 pop si ; Restore SI
327 pop ds ; Restore DS
328 ret
329%endif
330
331
332;--------------------------------------------------------------------
333; Returns string lenght. Strings must end to STOP character (strlen on C).
334;
335; String_StrLen
336; Parameters:
337; ES:DI: Pointer to string
338; Returns:
339; AX: String length in characters excluding STOP char
340; CF: Set if STOP character was found
341; Cleared if STOP character was not found
342; Corrupts registers:
343; Nothing
344;--------------------------------------------------------------------
345%ifdef USE_STR_LEN
346ALIGN JUMP_ALIGN
347String_StrLen:
348 push cx ; Store CX
349 mov al, STOP ; Load string end char to AL
350 mov cx, -1 ; Scan for maximum string length
351 call String_BuffHasChar ; Find offset for string ending char
352 pop cx ; Restore CX
353 ret
354%endif
355
356
357;--------------------------------------------------------------------
358; Returns length for token string. Token strings ends to any whitespace
359; character or to STOP.
360;
361; String_TokenLen
362; Parameters:
363; ES:DI: Pointer to token string
364; Returns:
365; AX: Token length in characters
366; Corrupts registers:
367; Nothing
368;--------------------------------------------------------------------
369%ifdef USE_STR_TOKEN
370ALIGN JUMP_ALIGN
371String_TokenLen:
372 push bx ; Store BX
373 xor bx, bx ; Zero BX for token length
374ALIGN JUMP_ALIGN
375.CharLoop:
376 mov al, [es:di+bx] ; Load character to AL
377 cmp al, STOP ; End of token?
378 je .Return ; If so, return
379 call String_IsSpace ; End of token?
380 jc .Return ; If so, return
381 inc bx ; Increment token length
382 jmp .CharLoop ; Loop while characters left
383ALIGN JUMP_ALIGN
384.Return:
385 mov ax, bx ; Copy string length to AX
386 pop bx ; Restore BX
387 ret
388%endif
389
390
391;--------------------------------------------------------------------
392; Returns index and ptr to first occurrence of
393; string 2 in string 1 (strstr on C).
394; Strings must be STOP terminated strings.
395;
396; String_StrWithin
397; Parameters:
398; DS:SI: Pointer to string 1
399; ES:DI: Pointer to string 2
400; Returns:
401; AX: Index to first occurrence of string 2 in string 1
402; DS:BX: Pointer to first occurrence of string 2 in string 1
403; CF: Set if string 2 was found in string 1
404; Cleared if string 2 was not found
405; Corrupts registers:
406; Nothing
407;--------------------------------------------------------------------
408%ifdef USE_STR_WITHIN
409ALIGN JUMP_ALIGN
410String_StrWithin:
411 push cx ; Store CX
412 push si ; Store SI
413 call String_StrLen ; Load str2 length to AX
414 mov cx, ax ; Copy str2 length to CX
415
416ALIGN JUMP_ALIGN
417.Str1CharLoop:
418 cmp BYTE [si], STOP ; End of string?
419 je .Str2NotFound ; If so, return FALSE
420 call String_BuffCmp ; str2 found in str1?
421 je .Str2Found ; If so, break loop
422 add si, ax ; Add index to first unmatching char
423 inc si ; Increment str1 ptr
424 jmp .Str1CharLoop ; Loop while characters left
425
426ALIGN JUMP_ALIGN
427.Str2Found:
428 mov bx, si ; Copy ptr to BX
429 mov ax, si ; Copy ptr to AX
430 pop si ; Restore SI
431 pop cx ; Restore CX
432 sub ax, si ; Calculate index to str2 in str1
433 stc ; Set CF since str2 found
434 ret
435ALIGN JUMP_ALIGN
436.Str2NotFound:
437 xor bx, bx ; Zero BX and clear CF
438 pop si ; Restore SI
439 pop cx ; Restore CX
440 ret
441%endif
442
443
444;--------------------------------------------------------------------
445; Returns pointer to wanted token inside STOP terminated string.
446; Tokens are separated by any white space characters.
447;
448; String_StrToken
449; Parameters:
450; CX: Index of token to return
451; ES:DI: Pointer to string
452; Returns:
453; AX: Token string length (if token found)
454; ES:DI: Pointer to token (if token found)
455; CF: Set if token found
456; Cleared if token not found
457; Corrupts registers:
458; Nothing
459;--------------------------------------------------------------------
460%ifdef USE_STR_TOKEN
461ALIGN JUMP_ALIGN
462String_StrToken:
463 push cx ; Store CX
464 push si ; Store SI
465 push ds ; Store DS
466 push es ; Copy ES:DI to DS:SI
467 pop ds
468 mov si, di
469 inc cx ; Increment to number of tokens to search
470 cld ; LODSB to increment SI
471ALIGN JUMP_ALIGN
472.ConsumeWhite:
473 lodsb ; Load char to AL from [DS:SI]
474 cmp al, STOP ; End of string?
475 je .NotFound ; If so, token was not found
476 call String_IsSpace ; Any whitespace character?
477 jc .ConsumeWhite ; If so, skip it
478 dec si ; Decrement SI to point first non-space
479 mov di, si ; Copy offset to token to DI
480ALIGN JUMP_ALIGN
481.TokenLoop:
482 lodsb ; Load char to AL
483 cmp al, STOP ; End of string?
484 je .EndOfString ; If so, end token
485 call String_IsSpace ; Any whitespace character?
486 jnc .TokenLoop ; If not, loop
487 loop .ConsumeWhite ; Loop until wanted token found
488.RetToken:
489 pop ds ; Restore DS
490 pop si ; Restore SI
491 pop cx ; Restore CX
492 call String_TokenLen ; Get token length to AX
493 stc ; Set CF since token found
494 ret
495ALIGN JUMP_ALIGN
496.EndOfString:
497 dec si ; Offset to STOP
498 cmp di, si ; STOP only char in token?
499 je .NotFound ; If so, then it is not valid token
500 loop .NotFound ; If last token was not wanted
501 jmp .RetToken
502ALIGN JUMP_ALIGN
503.NotFound:
504 pop ds ; Restore DS
505 pop si ; Restore SI
506 pop cx ; Restore CX
507 clc ; Clear CF since token not found
508 ret
509%endif
510
511
512;--------------------------------------------------------------------
513; Converts a STOP terminated string to unsigned 32-bit integer.
514;
515; String_StrToUInt
516; Parameters:
517; ES:DI: Pointer to string to convert
518; CX: Base (10=dec, 16=hex etc.)
519; Returns:
520; DX:AX: 32-bit unsigned integer
521; CF: Set if converted successfully
522; Cleared if error
523; Corrupts registers:
524; Nothing
525;--------------------------------------------------------------------
526%ifdef USE_STR_TOUINT
527ALIGN JUMP_ALIGN
528String_StrToUInt:
529 push si
530 call String_StrLen ; Get string length to AX
531 mov si, ax ; Copy length to SI
532 call String_BuffToUInt ; Convert to integer in DX:AX
533 pop si
534 ret
535%endif
536%if 0
537String_StrToUInt: ; Faster but we want to minimize size
538 ; Copy ES:DI to DS:SI
539 push ds ; Store DS
540 push si ; Store SI
541 push bx ; Store BX
542 mov si, di ; Copy ES:DI to DS:SI
543 push es
544 pop ds
545
546 ; Prepare to read chars
547 xor dx, dx ; Zero DX (HIWORD)
548 xor bx, bx ; Zero BX (LOWORD)
549ALIGN JUMP_ALIGN
550.CharLoop:
551 lodsb ; Load char to AL
552 cmp al, STOP ; End of string?
553 je .ConvComplete ; If so, break loop
554 call String_IsBaseChar ; Is valid character? (AH=digit)
555 jnc .RetFalse ; If not, return FALSE
556 xchg ax, bx ; AX=LOWORD, BX=digit and char
557 call Math_MulDWbyW ; DX:AX *= CX
558 xchg ax, bx ; AX=digit and char, BX=LOWORD
559 mov al, ah ; Copy digit to AL
560 xor ah, ah ; Zero AH, AX=digit
561 add bx, ax ; Add digit to LOWORD
562 adc dx, 0 ; Add carry to HIWORD
563 jmp .CharLoop ; Loop while valid characters
564ALIGN JUMP_ALIGN
565.ConvComplete:
566 stc ; Set CF since success
567ALIGN JUMP_ALIGN
568.RetFalse: ; If we jumped to here no CLC is needed to reflect a FALSE condition
569 mov ax, bx ; Copy loword to AX (may be incomplete)
570 pop bx ; Restore BX
571 pop si ; Restore SI
572 pop ds ; Restore DS
573 ret
574%endif
575
576
577;--------------------------------------------------------------------
578; Converts upper case character to lower case character.
579;
580; String_ToLower
581; Parameters:
582; AL: Character to convert
583; Returns:
584; AL: Character with possible conversion
585; Corrupts registers:
586; Nothing
587;--------------------------------------------------------------------
588%ifdef USE_STR_TOLOWER
589ALIGN JUMP_ALIGN
590String_ToLower:
591 call String_IsUpper ; Is upper case character?
592 jnc .Return ; If not, return
593 add al, 'a'-'A' ; Convert to lower case
594.Return:
595 ret
596%endif
597
598
599;--------------------------------------------------------------------
600; Converts lower case character to upper case character.
601;
602; String_ToUpper
603; Parameters:
604; AL: Character to convert
605; Returns:
606; AL: Character with possible conversion
607; Corrupts registers:
608; Nothing
609;--------------------------------------------------------------------
610%ifdef USE_STR_TOUPPER
611ALIGN JUMP_ALIGN
612String_ToUpper:
613 call String_IsLower ; Is lower case character?
614 jnc .Return ; If not, return
615 sub al, 'a'-'A' ; Convert to upper case
616.Return:
617 ret
618%endif
Note: See TracBrowser for help on using the repository browser.