source: xtideuniversalbios/trunk/Assembly_Library/Src/Display/DisplayFormatCompressed.asm @ 195

Last change on this file since 195 was 195, checked in by gregli@…, 12 years ago

Tiny optimization, switced to using a register that does not need to be preserved.

File size: 9.1 KB
Line 
1; Project name  :   Assembly Library
2; Description   :   Functions for displaying formatted strings.
3;                   ** Compressed Strings edition **
4;
5; Authors       :   Greg Lindhorst
6;               :   gregli@hotmail.com
7;               :       
8;               :   Tomi Tilli
9;               :   aitotat@gmail.com
10;               :
11; Description   :   This is a plug replacement for DisplayFormat.asm,
12;                   working instead with precompiled and slightly compressed strings.
13;
14; Strings are compressed in a simple manner:
15;   1. The two most common characters, space and null, are removed
16;   2. Format specifiers are reduced to a single byte, including length information
17;
18; Format of bytes in the string are:
19;     01 xxxxxx     Character in x plus StringsCompressed_NormalBase
20;     10 xxxxxx     Character in x plus StringsCompressed_NormalBase, followed by a null (last character)
21;     11 xxxxxx     Character in x plus StringsCompressed_NormalBase, followed by a space       
22;     00 1 yyyyy    Character/Format in lookup table StringsCopmressed_TranslatesAndFormats
23;     00 0 yyyyy    Character/Format in lookup table StringsCompressed_TranslatesAndFormats, followed by a null
24;
25; StringsCompressed_NormalBase is defined by the compressor, but is usually around 0x40,
26; which gives a range of 0x40 to 0x7f, or roughly the upper and lower case letters.
27;
28; StringsCompressed_TranslatesAndFormats is a lookup table with the first few bytes being translation
29; characters, and the last few bytes being format jump offsets from DisplayFormatCompressed_BaseFormatOffset.
30; The dividing line is defined by StringsCompressed_FormatsBegin
31;
32; The assignments of the first two bits above is not by accident.  The translates/format branch is 00
33; which is easy to test for.  The '01' for "normal" (no null or space) and '001' for translates/format "normal" 
34; match, allowing the translates/format codes to be shifted left by 1 and then tested with the same instructions.
35;
36; It is always possible to say that a null character follows the current character - thus there is 
37; no way (nor need) to specify a zero character.
38;
39; Note that this code is optimized for size, not speed.  Since this code is used only during initialization
40; and only for the user interface, small performance hits should not be noticed.  It will seem odd to do so
41; much "preload", just in case a branch is taken, but that is cheaper (in size) than adding additional branches.
42;
43       
44; Section containing code
45SECTION .text
46
47;--------------------------------------------------------------------
48; Format Handlers
49;
50; Names of format handlers are DisplayFormatCompressed_Format_* where * is
51; replaced with the format code after the '%' in the original string, 
52; with '-' replaced with '_'.
53;
54;   Parameters:
55;       DS:     BDA segment (zero)
56;       AX:     Parameter to Format
57;       ES:DI:  Ptr to cursor location in video RAM
58;   Returns:
59;       DI:     Updated offset to video RAM
60;   Corrupts registers:
61;       AX, BX, CX, DX, SI
62;--------------------------------------------------------------------
63
64;
65; The following routines do not need any pre or post processing and can be jumped to directly.
66; Note that they need to be within 256 bytes of DisplayFormatCompressed_BaseFormatOffset
67;
68%define DisplayFormatCompressed_Format_c DisplayPrint_CharacterFromAL
69%define DisplayFormatCompressed_Format_nl DisplayPrint_Newline_FormatAdjustBP
70%define DisplayFormatCompressed_Format_s DisplayFormat_ParseCharacters_FromAX
71
72DisplayFormatCompressed_Format_A:
73    mov     [VIDEO_BDA.displayContext+DISPLAY_CONTEXT.bAttribute], al
74DisplayFormatCompressed_ret:            ; jump target for other routines who need a "ret"
75    ret
76
77DisplayFormatCompressed_Format_x:
78DisplayFormatCompressed_Format_5_x:
79    mov     si,16                       ; hex output, change base to 16
80    mov     bx,(04<<8) + 'h'            ; 4 bytes, with postfix character 'h' to emit
81                                        ; (note that the count includes the 'h')
82    jmp     DisplayFormatCompressed_Format_u
83
84DisplayFormatCompressed_Format_2_I:
85    mov     si,g_szDashForZero          ; preload dash string in case we jump
86    test    ax,ax                       ; if parameter equals zero, emit dash string instead
87    jz      DisplayFormat_ParseCharacters
88    ; fall through
89       
90DisplayFormatCompressed_Format_2_u:
91    mov     bh,2                        ; only two characters (instead of the default 5)
92    ; fall through
93       
94DisplayFormatCompressed_Format_u:
95DisplayFormatCompressed_Format_5_u:
96    push    bx                          ; push postfix character - either a zero (default) or a 'h'
97    mov     bl,bh                       ; preserve character count for .PrintLoop
98
99.DivLoop:
100    xor     dx, dx                      ; Zero DX for division
101    div     si                          ; DX:AX / 10 => AX=quot, DX=rem
102    push    dx                          ; Push digit
103       
104    dec     bh                         
105    jnz     .DivLoop
106
107.PrintLoop:
108    pop     ax                          ; Pop digit, postfix character on last iteration
109
110    dec     bl                          ; on second to last iteration, emit digit whether it is zero or not
111    jz      .PrintDigit
112
113    js      short DisplayPrint_CharacterFromAL  ; on last iteration, emit postfix character
114                                                ; if it is zero, DisplayPrint_CharacterFromAL will not emit
115
116    or      bh, al                      ; skip leading zeros, bh keeps track if we have emitted anythng non-zero
117    jnz     .PrintDigit                 ; note that bh starts at zero, from the loop above
118
119    test    ch,2                        ; are we padding with leading spaces? 
120    jnz     .PrintLoop                  ; test the even/odd of the format byte in the string
121
122    mov     al,' '-'0'                  ; emit space, but let the following instuctions add '0'
123
124.PrintDigit:   
125    add     al,'0'                      ; Digit to character
126    cmp     al,'9'                      ; for hex output, greater than '9'?
127    jle     .NoHexAdjustment
128    add     al,'A'-'9'-1                ; adjust for hex output ('A' to 'F')
129.NoHexAdjustment:       
130
131    call    DisplayPrint_CharacterFromAL
132
133    jmp     .PrintLoop
134
135       
136;--------------------------------------------------------------------
137; DisplayFormat_ParseCharacters
138;   Parameters:
139;       DS:     BDA segment (zero)
140;       SS:BP:  Pointer to first format parameter (-=2 updates to next parameter)
141;       CS:SI:  Pointer to string to format
142;       ES:DI:  Ptr to cursor location in video RAM
143;   Returns:
144;       CS:SI:  Ptr to end of format string (ptr to one past NULL)
145;       DI:     Updated offset to video RAM
146;   Corrupts registers:
147;       AX, BX, CX, DX, BP
148;--------------------------------------------------------------------       
149
150DisplayFormatCompressed_BaseFormatOffset:
151       
152DisplayFormat_ParseCharacters_FromAX:
153    mov     si,ax
154    ; fall through to DisplayFormat_ParseCharacters
155
156ALIGN JUMP_ALIGN       
157DisplayFormat_ParseCharacters: 
158;
159; This routine is used to outptu all strings from the ROM.  The strings in ROMVARS are not compressed, 
160; and must be handled differently.
161;
162    cmp     si,byte 07fh        ; well within the boundaries of ROMVARS_size
163    mov     bx,cs               ; preload bx with cs in case we take the following jump
164    jb      short DisplayPrint_NullTerminatedStringFromBXSI
165
166.decode:
167    mov     al,[cs:si]          ; load next byte of the string
168    inc     si
169
170    mov     ch,al               ; save a copy for later processing of high order bits
171
172    test    al,0c0h             ; check for translation/format character
173    jz      DisplayFormatCompressed_TranslatesAndFormats
174
175    and     al,03fh                             ; "Normal" character, mask off high order bits
176    add     al,StringsCompressed_NormalBase     ; and add character offset (usually around 0x40)
177       
178.output:
179    call    DisplayPrint_CharacterFromAL       
180
181.process_after_output:
182    shl     ch,1                                ; check high order bits for end of string or space
183    jns     short DisplayFormatCompressed_ret
184    jnc     .decode
185    mov     al,' '
186    call    DisplayPrint_CharacterFromAL
187    jmp     .decode
188
189
190ALIGN JUMP_ALIGN
191DisplayFormatCompressed_TranslatesAndFormats:       
192;
193; This routine is here (above DisplayFormat_ParseCharacters) to reduce the amount of code between
194; DisplayFormatCompressed_BaseFormatOffset and jump targets (must fit in 256 bytes)
195;
196    shl     ch,1                ; setup ch for later testing of null in .process_after_output
197    and     ax,0001fh           ; also clears AH for addition with BX and DX below
198
199    mov     bx,StringsCompressed_TranslatesAndFormats   ; calculate offset of translation/formats offset byte
200    add     bx,ax
201
202    cmp     al,StringsCompressed_FormatsBegin           ; determine if this is a translation or a format
203                                                       
204    mov     al,[cs:bx]                                  ; fetch translation/formats byte
205
206    jb      DisplayFormat_ParseCharacters.output        ; check if this a translation or a format
207                                                        ; if it is translation, output and postprocess for eos
208                                                        ; note that the flags for this conditional jump were
209                                                        ; set with the cmp al,StringsCompressed_FormatsBegin
210       
211    mov     dx,DisplayFormatCompressed_BaseFormatOffset   ; calculate address to jump to for format handler
212    sub     dx,ax
213
214    mov     ax,[bp]             ; preload ax with parameter
215    dec     bp                  ; if no parameter is needed (format 'nl' for example),
216    dec     bp                  ; the format handler can reincrement bp
217
218    mov     bx,0500h            ; preload bh with 5 decimal places for numeric output
219                                ; bl is zero, indicating not to output a 'h' (default base 10)
220
221    push    si                  ; preserve si and cx, in the case of outputing a string
222    push    cx
223
224    mov     si,10               ; preload si with 10 for numeric output (default base 10)
225
226    call    dx                  ; call the format routine
227
228    pop     cx                  ; restore cx and si
229    pop     si
230
231    jmp     DisplayFormat_ParseCharacters.process_after_output  ; continue postprocessing, check for end of string
232
233
234
235
236
237
238       
239
240       
241   
242
243
Note: See TracBrowser for help on using the repository browser.