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

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