source: trunk/bootcode/regular/conv.asm

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

This one is needed when debugging [v1.1.3-testing]

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.2-manual.pdf

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