I'm trying to convert packed decimal numbers into ascii strings. Here is my understanding thus far:
The following:
bcd BYTE 34h
Should convert to the decimal number 34 after being "unpacked". Now I'm not sure on the best way of doing this. If I convert this hexadecimal number to binary it is as follows...
0011 0100
Now, if I have my procedure print out each 4bit binary value at a time, then it should print the ascii string of numbers, correct? So if I go through a loop, grab the first 4 bit binary number, print its actual value out, its going to print 3.. then do the same, its going to print 4.
So, here is my general idea:
Take an 8bit value "34h", mov it into AH and AL. In AH, clear the second half of the bits using the follow:
and ah, 11110000b
and in AL, clear the first half of the bits using the following:
and al, 00001111b
So AH = 0110b or 3 And AL = 0100b or 4, then print these out accordingly..
Is this a good approach? Or am I going about completely incorrect or way over thinking it?
EDIT: Here is my final solution with original value of 12345678h. Thanks to all who helped!
;-----------------------------------------------------------------------------
PackedToAsc PROC USES eax ebx edx ecx esi
; This function displays a packed decimal value in its "ascii" form
; i.e. 12345678h would display decimal, 12345678 in decimal form
;
; Requires ECX = SIZEOF packed decimal
; ESI to be pointing to the packed decimal
;-----------------------------------------------------------------------------
mov edx, [esi] ; temp store our offset
mov eax, 0 ; clear eax
mov ebx, 0 ; clear ebx
L1: rol edx, 8 ; rotate left 8 bits to avoid little endian
mov [esi], edx ; mov our temp back to the actual value
mov al, BYTE PTR [esi] ; al = 12h 0001 0010
mov bl, BYTE PTR [esi] ; bl = 12h 0001 0010
shr al, 4 ; al = 0000 0001
and bl, 00001111b; ; bl = 0000 0010
add al, 48 ; convert to ascii
call WriteChar ; display al
mov al, bl
add al, 48 ; convert to ascii
call WriteChar ; display bl
loop L1
call Crlf
ret
PackedToAsc END
P
BCD uses only the digits 0 thru 9.
An unpacked BCD digit uses the lower nibble of an entire byte and to convert it to ASCII you add 48.
The number 34h is 52 decimal and will be represented as an unpacked BCD as 00000101 and 00000010
(Changed to avoid confusion when using built-in instructions)
When it is packed: 01010010 == BCD packed 52
To unpack it, you can do as you have done, but you need to shift AH right to place the value in the lo-nibble. To convert to ASCII just add 48.
[edit]
MASM (=> ALL instructions, Linux included) that runs on 80x86 processors uses the little-endian scheme. CPUs such as Motorola 68000 (Apple Mac) and RISC uses big-endian.
When you store a number as BCD, the least significant byte is at the lowest address thru to the most-significant at the highest, e.g.:
my_unpacked_bcd DB 4,3,2,1 ; this is the decimal number 1234
my_packed_bcd DW 3412h ; this defines the same number as packed
Packed BCD depends on what you want to do with it. If you want to ADD, MUL, DIV, SUB
you must present the values as required by these instructions. Also remember to add zero-bytes to start and end of your digits to hold carries.