The Challenge
-------------
Write a routine for converting ASCII hex to binary in 6 bytes.
The Solution
Well, actually, I cheated: I found the following text on the internet a few
months ago and decided to see if I could beat it:
===================================================================-Asc2hex.txt
An efficient algorithm for converting ASCII hex to binary
Ken Sykes (72177,141)
David Ogle (75676,2612)
There is a well-known algorithm for converting a binary number between
one and fifteen to its equivalent hex form in ASCII that only requires
four assembly language instructions. Assuming that the number to convert is
in AL, the following sequence performs the conversion:
add al,90h
daa
adc al,40h
daa
This instruction sequence is, as far as we know, the shortest (16 cycles)
self-contained routine to convert a binary number to hex. Inspired by
this code and the fact that a similar routine to convert ASCII hex to
binary would be useful, we came up with two algorithms that convert an
ASCII hex digit to binary in five assembly instructions or less.
The first algorithm takes advantage of an undocumented feature of the
8088. The AAM instruction (Ascii Adjust for Multiply) divides AL by 10,
placing the remainder in AL and the quotient in AH. The opcode for
AAM is: 0D4h,0Ah. It's no coincidence that the second byte is 10 - the
8088 uses the second byte of the opcode as the divisor! The same rule
applies to the AAD (Ascii Adjust for Division) instruction. With this in
mind, a conversion routine goes as follows (assuming the ASCII digit is in
AL and in the range '0..9,A..F'):
The only problem is the Microsoft Assembler does not accept this form.
By placing the opcodes in data statements, however, the following code
will assemble properly:
sub al,'0'
db 0D4h,10h
db 0D5h,09h
At three instructions and six bytes of code space, We are reasonably
sure this is the shortest self-contained sequence to perform the conversion.
The only drawbacks are the use of non-standard opcodes and the execution
time (147 cycles!). The second algorithm, loosely-based on this one,
relieves these restrictions.
The second algorithm makes exclusive use of fast instructions to
perform the conversion (again, AL holds the digit to convert):
add al,40h
cbw
and ah,09h
add al,ah
and al,0Fh
While two additional instructions are required, the routine executes
in 17 cycles. We are reasonably sure this is the fastest-executing selfcontained
code to perform the conversion. It has the added benefit of
handling the ASCII values 'a'..'f'.
These algorithms will hopefully trim down the execution times of your
programs, and we welcome any suggestions or improvements on our code.
Happy Hacking!
===========================================================================-EOF
Sadly, I was unable to come up with a smaller version, or a faster one. Tinara
posted a similar solution to the APJ Message Board:
SUB AL, 30h
AAM 10h ; db D4h, 10h
AAD 09h ; db D5h, 09h
...so he gets kudos for uncovering by work what I managed by stealth. As for
next issue, I haven't had time to prepare a challenge, but I'm sure one will
crop up in the next month or so.
Next Issue Challenge
None so far... submissions welcome.
|