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

Last change on this file since 196 was 195, checked in by gregli@…, 13 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.