source: trunk/bootcode/regular/conv.asm@ 87

Last change on this file since 87 was 87, checked in by Ben Rietbroek, 8 years ago

Added function to convert a byte to packed BCD [v1.1.1-testing]

This enabled displaying small numbers (0>=n<=255) as decimal values.
The function returns a 16-bit value with the number of decimal digits
in the high nibble and the decimal digits in the remaining nibbles.

CAUTION:
This is a testbuild !
AirBoot uses the BIOS to access disks and a small coding error can trash
partition tables or other vital disk structures. You are advised to make
backups of TRACK0 and EBRs before using this testbuild. More info at:
https://rousseaux.github.io/netlabs.air-boot/pdf/AirBoot-v1.1.0-manual.pdf

File size: 14.5 KB
Line 
1; AiR-BOOT (c) Copyright 1998-2008 M. Kiewitz
2;
3; This file is part of AiR-BOOT
4;
5; AiR-BOOT is free software: you can redistribute it and/or modify it under
6; the terms of the GNU General Public License as published by the Free
7; Software Foundation, either version 3 of the License, or (at your option)
8; any later version.
9;
10; AiR-BOOT is distributed in the hope that it will be useful, but WITHOUT ANY
11; WARRANTY: without even the implied warranty of MERCHANTABILITY or FITNESS
12; FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
13; details.
14;
15; You should have received a copy of the GNU General Public License along with
16; AiR-BOOT. If not, see <http://www.gnu.org/licenses/>.
17;
18;---------------------------------------------------------------------------
19; AiR-BOOT / CONVERSION
20;---------------------------------------------------------------------------
21
22
23; ----------------------
24; Rousseau: # CONV.ASM #
25; ----------------------
26; This module contains various conversion routines.
27; Some have to do with bin to ascii, others with translation.
28
29
30IFDEF MODULE_NAMES
31DB 'CONV',0
32ENDIF
33
34; Convert a byte in AL to it's Hex Ascii value.
35; In: AL - value to convert
36; Out: AX - two (Hex) Ascii digits
37; Destroyed: none
38CONV_BinToAsc Proc Near
39 mov ah,al ; Save value to process high nibble later
40 and al,0fh ; Mask low nibble
41 add al,'0' ; Convert to ASCII
42 cmp al,'9' ; Is it in the range of '0' - '9' ?
43 jbe CONV_BinToAsc_DecDigit_1 ; Yep, done
44 add al,7 ; Nope, adjust to Hex Ascii
45 CONV_BinToAsc_DecDigit_1:
46 xchg al,ah ; Exchange with saved value to process high nibble
47 shr al,4 ; Move high nibble to low nibble (80186+)
48 ;shr al
49 ;shr al
50 ;shr al
51 add al,'0' ; Convert to ASCII
52 cmp al,'9' ; Is it in the range of '0' - '9' ?
53 jbe CONV_BinToAsc_DecDigit_2
54 add al,7 ; Nope, adjust to Hex Ascii
55 CONV_BinToAsc_DecDigit_2:
56 xchg al,ah ; Correct order, AX now contains the two (hex) digits
57 ret
58CONV_BinToAsc Endp
59
60
61
62; Convert a byte in AL to it's packed BCD value in AX.
63; In: AL - value to convert
64; Out: AX - |digitcount|digit2|digit1|digit0|
65; Destroyed: none
66CONV_BinToPBCD Proc Near uses cx
67
68 ; Use AAM to convert to unpacked BCD
69 mov ch, 1 ; There always is at least one digit
70 aam ; Convert byte to unpacked BCD
71 test ah, ah ; If AH is zero, the value was below 10d
72
73 ; Just one digit, we're done
74 jz CONV_BinToPBCD_done
75
76 ; There are more digits
77 inc ch ; Increment digit count
78 cmp ah, 9 ; If AH is above 9, there is a third digit
79
80 ; There are three digits, AH needs to be processed too
81 ja CONV_BinToPBCD_three_digits
82
83 ; There are two digits, AH contains second digit
84 shl ah, 4 ; Correct the unpacked BCD nibble location
85 or al, ah ; Now we have a 2 digit packed BCD
86 xor ah, ah ; No third digit
87
88 ; Two digits, we're done
89 jmp CONV_BinToPBCD_done
90
91 CONV_BinToPBCD_three_digits:
92 ; There are three digits, process AH
93 inc ch ; Increment digit count
94 mov cl, al ; Store the first digit
95 mov al, ah ; Value in AH needs to be processed also
96 aam ; Convert byte to unpacked BCD
97 shl al, 4 ; Correct the unpacked BCD nibble location
98 or al, cl ; Merge the first BCD digit
99
100 ; Three digits, we're done
101 jmp CONV_BinToPBCD_done
102
103 CONV_BinToPBCD_done:
104 ; Compose the packed BCD value with the digit count in high nibble
105 shl ch, 4 ; Move count to correct nibble
106 or ah, ch ; Count is now in high nibble of AX
107 test ax, 0fffh ; Set ZF if all digits are 0
108
109 ret
110CONV_BinToPBCD Endp
111
112
113
114; See if a character is printable.
115; Replace with a '.' if not.
116; In: AL - char to print
117; AH - char to print if AL is non-printable
118; Out: AL - char printed (could be dot)
119; Destroyed: none
120CONV_ConvertToPrintable Proc Near
121 cmp al,20h
122 jb CONV_ConvertToPrintable_NP ; Below space, so not printable
123 cmp al,7eh ; Above tilde, so not printable
124 ja CONV_ConvertToPrintable_NP
125 jmp CONV_ConvertToPrintable_End ; Go output it
126 CONV_ConvertToPrintable_NP:
127 mov al,ah ; Use the replacement character
128 CONV_ConvertToPrintable_End:
129 ret
130CONV_ConvertToPrintable EndP
131
132
133
134; Convert CHS values to LBA address
135; Formula: LBA = ((c * H) + h) * S + s -1
136; c,h,s: requested
137; H,S: heads per cylinder and sectors per track
138; In: DX:AX - Cylinder
139; BX - Head
140; CX - Sector
141; Out: BX:CX:DX:AX - LBA address (64-bits)
142; ZF=1 if upper 32-bits are zero (LBA32)
143; Destroyed: none
144CONV_CHS2LBA Proc Near
145 local req_cyl:dword
146 local req_head:word
147 local req_sec:word
148 local lba:qword
149
150 ; Save parameters
151 mov word ptr [req_cyl],ax ; save low cyl
152 mov word ptr [req_cyl+2],dx ; save high cyl
153 mov [req_head],bx ; save head
154 test cx,cx
155 jnz CONV_CHS2LBA_sec_ok
156 mov cx,1 ; cannot have sector 0, so change to 1
157 CONV_CHS2LBA_sec_ok:
158 dec cx ; prepare for calculation later
159 mov [req_sec],cx ; save sec
160
161 ; Clear return value
162 xor ax,ax
163 mov word ptr [lba+6],ax
164 mov word ptr [lba+4],ax
165 mov word ptr [lba+2],ax
166 mov word ptr [lba+0],ax
167
168 ; Cyls * Heads
169 mov dx,word ptr [req_cyl+2] ; high word of requested cylinder
170 mov ax,word ptr [req_cyl+0] ; low word of requested cylinder
171 xor bx,bx ; zero for 32-bit math
172 mov cx,word ptr [BIOS_Heads] ; number of heads
173 call MATH_Mul32
174
175 ; WE DISCARD HIGH 32-BITS HERE BECAUSE CALCULATION
176 ; WOULD REQUIRE 64-bits MATH.
177 ; THIS WILL BE FIXED LATER.
178 ; THIS MEANS LBA >2TiB IS NOT SUPPORTED YET.
179
180 ; Add requested head
181 add ax,[req_head]
182 adc dx,0
183 ;adc cx,0
184 ;adc bx,0
185
186 ; * Secs
187 xor bx,bx
188 mov cx,word ptr [TrueSecs] ; Implicitly address disk 80h
189 call MATH_Mul32
190
191 ; Add requested sec
192 add ax,[req_sec]
193 adc dx,0
194 ;adc cx,0
195 ;adc bx,0
196
197 xor bx,bx
198 xor cx,cx
199
200 ; Set ZF if high upper 32-bits are zero
201 or bx,cx
202
203 ret
204CONV_CHS2LBA EndP
205
206
207CONV_LBA2CYLS Proc Near
208 ret
209CONV_LBA2CYLS Endp
210
211
212; Convert a character to upper-case
213CONV_ToUpper Proc Near
214 cmp al,'a'
215 jb CONV_ToUpperSkip1
216 cmp al,'z'
217 ja CONV_ToUpperSkip1
218 sub al,20h
219 CONV_ToUpperSkip1:
220 ret
221CONV_ToUpper EndP
222
223
224;
225; The bitfield functions below are used to pack values into arrays.
226; A buffer needs to be provided, a bitfield width and an index into the array.
227; These functions are used to pack the hidden partition-table which is
228; too small in the 45-partition version.
229;
230
231
232; IN: DL = Index to store bitfield
233; DH = Bitfield width (1-8)
234; BX = Pointer to bitfield array
235; OUT: AL = Value of requested bitfield
236; AH = Mask value
237CONV_GetBitfieldValue Proc Near Uses bx cx dx
238 ; Normalize bit-width in DH.
239 dec dh ; Decrement bitfield width to mask invalid values.
240 and dh,07h ; Only 3 bits are significant to determine width.
241 mov cl,dh ; Save for later use to calculate mask.
242 inc dh ; Put back to normalized value.
243
244 ; Calculate corresponding AND-mask in CH.
245 mov ch,2 ; Were going to shift 2...
246 shl ch,cl ; to obtain the mask corresponding...
247 dec ch ; to the bitfield width.
248
249 ; Calculate byte-index.
250 mov al,dl ; Index in AL.
251 inc al ; Increment for calculations.
252 mul dh ; Multiply by bitfield width to get bits.
253 mov cl,8 ; Nr. of bits in a byte.
254 div cl ; Divide to get byte index.
255
256 ; Advance pointer to byte-index.
257 add bl,al ; Advance pointer...
258 adc bh,0 ; to byte index.
259
260 ; Determine if we need 1 or 2 byte access to extract the bitfield.
261 mov cl,ah ; Get remainder in CL.
262 sub cl,dh ; Substract bitfield width to get shift-count.
263 mov ah,0 ; Prepare upper=0 when field spans no byte bound.
264 ; Don't change to xor ah,ah or any CY will be lost.
265
266 ; Jump if the bitfield does not span byte boundaries.
267 ; (Remainder - bitfield width >= 0)
268 jae CONV_GetBitfieldValue_nospan
269
270 ; Bit-field spans byte boundaries, so adjust shift-count
271 ; and use AH to get first part of bitfield.
272 add cl,8 ; Adjust shift-count.
273 mov ah,[bx] ; Get byte into AH instead.
274 dec bx ; Adjust pointer to load rest of bitfield.
275
276 CONV_GetBitfieldValue_nospan:
277 mov al,[bx] ; Load (rest of) bitfield into AL.
278 shr ax,cl ; Shift bitfield to the right.
279 mov ah,ch ; Get mask in AH.
280 and al,ah ; Mask value.
281 ret
282CONV_GetBitfieldValue EndP
283
284
285
286
287; IN: AL = Value to store
288; DL = Index to store bitfield
289; DH = Bitfield width (1-8)
290; BX = Pointer to bitfield array
291; OUT: AL = Value of stored bitfield
292; AH = Mask value
293CONV_SetBitfieldValue Proc Near Uses bx cx dx
294 ; Push value for later use.
295 push ax
296
297 ; Normalize bit-width in DH.
298 dec dh ; Decrement bitfield width to mask invalid values.
299 and dh,07h ; Only 3 bits are significant to determine width.
300 mov cl,dh ; Save for later use to calculate mask.
301 inc dh ; Put back to normalized value.
302
303 ; Calculate corresponding AND-mask in CH.
304 mov ch,2 ; Were going to shift 2...
305 shl ch,cl ; to obtain the mask corresponding...
306 dec ch ; to the bitfield width.
307
308 ; Calculate byte-index.
309 mov al,dl ; Index in AL.
310 inc al ; Increment for calculations.
311 mul dh ; Multiply by bitfield width to get bits.
312 mov cl,8 ; Nr. of bits in a byte.
313 div cl ; Divide to get byte index.
314
315 ; Advance pointer to byte-index.
316 add bl,al ; Advance pointer...
317 adc bh,0 ; to byte index.
318
319 ; Determine if we need 1 or 2 byte access to extract the bitfield.
320 mov cl,ah ; Get remainder in CL.
321 sub cl,dh ; Substract bitfield width to get shift-count.
322
323 ; Restore value to poke.
324 pop ax
325
326
327 ; Jump if the bitfield does not span byte boundaries.
328 ; (Remainder - bitfield width >= 0)
329 jae CONV_SetBitfieldValue_nospan
330
331 ; Bit-field spans byte boundaries, so adjust shift-count
332 ; and use 16-bit access.
333 add cl,8 ; Adjust shift-count.
334
335 ; Merge the bitfield to the array.
336 push cx ; Save mask (CH) and shift-count (CL).
337 push ax ; Save value to store.
338 xor ah,ah ; Clear upper byte so we can shift in it.
339 and al,ch ; Mask value.
340 shl ax,cl ; Move the bitfield to the proper location.
341 mov dh,[bx] ; Get 1st part of bitfield from array.
342 dec bx ; Adjust pointer.
343 mov dl,[bx] ; Get 2nd part of bitfield from array.
344 push bx ; We need BX so save it.
345 xor bh,bh ; Clear upper byte so we can shift in it.
346 mov bl,ch ; Put mask in BL.
347 shl bx,cl ; Shift mask to proper location.
348 not bx ; Complement it to mask-out the required bitfield.
349 and dx,bx ; Mask-out the required bitfield.
350 pop bx ; Restore pointer.
351 or ax,dx ; Merge the bitfields.
352 mov [bx],al ; Store lower byte.
353 inc bx ; Adjust pointer.
354 mov [bx],ah ; Store upper byte.
355 pop ax ; Restore value.
356 pop cx ; Restore mask and shift-count.
357
358 ; Done.
359 jmp CONV_SetBitfieldValue_end
360
361 CONV_SetBitfieldValue_nospan:
362 ; Merge the bitfield to the array.
363 push cx ; Save mask (CH) and shift-count (CL).
364 push ax ; Save value to store.
365 and al,ch ; Mask value.
366 shl al,cl ; Move the bitfield to the proper location.
367 mov dl,[bx] ; Get byte containing bitfield.
368 shl ch,cl ; Shift mask to proper location.
369 not ch ; Complement it to mask-out the required bitfield.
370 and dl,ch ; Mask-out the required bitfield.
371 or al,dl ; Merge the bitfields.
372 mov [bx],al ; Store byte containing bitfield.
373 pop ax ; Restore value.
374 pop cx ; Restore mask and shift-count.
375
376 CONV_SetBitfieldValue_end:
377 mov ah,ch ; Get mask in AH.
378 and al,ah ; Mask value.
379 ret
380CONV_SetBitfieldValue EndP
381
Note: See TracBrowser for help on using the repository browser.