Conversion from HEX to ASCII |
|
In embedded programming, the basic problem is user interface. Besides reading data from the keyboard, printing to the display, etc., various conversions are also encountered.
Although it may seem primitive, this option is widely used. First, it is simple, and it can achieve high speed that does not depend on the number being converted. It can also convert into a representation different than 0123456789ABCDEF, for example to the Hewlett-Packard representation of 0123456789ACFHPU (used in signature analysis etc.), which is more legible on 7-segment displays.
Table lookup corresponds roughly to the following C-like fragment:
const code char HEXstring[16] = "0123456789ABCDEF";
print_hex (BYTE num)
{
put_nibble (num >> 4);
put_nibble (num);
}
put_nibble (BYTE nibble)
{
char_from_Acc (HEXstring[nibble & 0x0F]);
}In ASM51 the following code might be used:
print_hex1:;
PUSH ACC ;store LSB for later
SWAP A ;move MSB from bits 7..4 to 3..0
ACALL put_nibble1 ;print MSB part
POP ACC ;restore value
ACALL put_nibble1 ;print LSB part
RET
;
put_nibble1:
ANL A,#0FH ;use only LSB
ADD A,#HEXstring1-mvcoff1 ;read table offset
MOVC A,@A+PC ;use it as an index to retrieve the ASCII value
mvcoff1:
ACALL char_from_Acc ;print fetched value
RET
HEXstring1:
DB '0123456789ABCDEF'
; 34 bytes, execution time 31 µs at 12 MHz
;After removing unnecessary CALL and RETURN, the following modification is obtained:
print_hex2:
PUSH ACC
SWAP A
ACALL put_nibble2
POP ACC
;
put_nibble2:
ANL A,#0FH
ADD A,#HEXstring2-mvcoff2
MOVC A,@A+PC
mvcoff2:
AJMP char_from_Acc
HEXstring2:
DB '0123456789ABCDEF' ;'standard' hex string
; DB '0123456789ACFHPU' ;HP signature analysis
;
; 30 bytes, execution time 23 µs at 12 MHz
;Simple elimination of redundant procedure calls shortens execution time from 31 top 23 µs and even shortens the code by 4 bytes. To make it even faster, we have to eliminate the put_nibble call, placing the procedure inline instead of the call.
print_hex3:
PUSH ACC
SWAP A
ANL A,#0FH
ADD A,#HEXstring3-mvcoff3a
MOVC A,@A+PC
mvcoff3a:
ACALL char_from_Acc
POP ACC
ANL A,#0FH
ADD A,#HEXstring3-mvcoff3b
MOVC A,@A+PC
mvcoff3b:
AJMP char_from_Acc
HEXstring3:
DB '0123456789ABCDEF' ;'standard' hex string
; DB '0123456789ACFHPU' ;HP signature analysis
;
; 35 bytes, execution time 21 µs at 12 MHz
;Inline procedures shorten execution time by another 2 µs but the code is 5 bytes longer.
This is used quite often because it is easy to understand.
The conversion algorithm corresponds to the following C-like fragment
print_hex (BYTE num)
{
put_nibble (num >> 4);
put_nibble (num);
}
put_nibble (BYTE nibble)
{
nibble = nibble & 0x0F; //True C lovers would write nibble &= 0x0F
if (nibble > 10) nibble = nibble + 'A' - ('9' + 1);
char_from_Acc (nibble + '0');
}In ASM51, the following code might be used:
print_hex4:
PUSH ACC
SWAP A
ACALL put_nibble4
POP ACC
put_nibble4:
ANL A, #0Fh
ADD A, #-10 ;processor cannot directly compare to a constant
;so we'll use subtraction instead
JNC phex_n
ADD A, #7
phex_n:
ADD A, #'0'+10 ;+10 is added since storing a value before comparison
;and restoring itwould be less effective
AJMP char_from_Acc
;
; 19 bytes, execution time 25,75 µs at 12 MHz
;
Even this algorithm could be improved, for example by substituting
ADD A,#7
with
ADD A,#'A'+10
AJMP char_from_Acc
This option is simple, short and elegant; however, it is not that easy to understand.
print_hex5:;
PUSH ACC
SWAP A
ACALL put_nibble5
POP ACC
put_nibble5:
ANL A,#0Fh
ADD A,#90h ;conversion from 00h..0Fh range to 90h..9Fh
DA A ;does nothing for 90h..99h range
;for 9Ah..9Fh range:
; 1) adds 06h, converting to A0h..A5h
; 2) adds 60h to the result, converting to 00h..05h and setting Carry
ADDC A,#40h ;converts from 90h..99h to D0h..D9h + Carry
;converts from 00..05h(+Carry) to 41h..45h
DA A ;for range D0h..D9h(+Carry) adds 60h, converting to 30h..39h
;does nothing for 41h..45h
AJMP char_from_Acc
; 17 bytes, execution time 25 µs at 12 MHz
;
char_from_Acc:
RET ;dummy procedure
;
Each option has its advantages as well as disadvantages, as the following table shows:
| Code size (bytes) |
Execution time (µs at 12 MHz) |
Note | |
|---|---|---|---|
| Table lookup ver. 1 | 34 | 31 | |
| Table lookup ver. 2 | 30 | 23 | Universal |
| Table lookup ver. 3 | 35 | 21 | Fastest |
| Comparisons | 19 | 25,75 | |
| DAA trick | 17 | 25 | Smallest |
Note: Execution time is the average for all 256 possible values.
| Web51 description | News | FAQ | ORDER FORM | DOWNLOAD | Links |
| (c)Copyright 2000 - 2002, HW server & Radek Benedikt
Web51@HW.cz, Web51.HW.cz |
|