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

Last change on this file since 3 was 3, checked in by aitotat, 14 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.