Today, I needed this one.
Again, OA32 was missing this function.
So again, I kludged one together.
It's a little prettier than the previous Dec2Qword function was.. and I expect to use it more often, so that's good.

This function looks for hex strings in C's 0xFF format, and MASM's 0FFh format - but does not expect them.
This algorithm is a lot easier to implement, each hex character represents 4 bits of the answer.




hex2qword proc uses esi edi pHexString:LPSTR
LOCAL toggle:byte
LOCAL lowbits:byte
LOCAL Val:qword
mov toggle,0
lea edi,Val
qdmov ,0

mov eax,pHexString
.if word ptr=="x0"
add pHexString,2   ;skip prefix
.endif
invoke lstrlen,pHexString
DbgDec eax
add eax,pHexString
mov esi,eax

.while esi>pHexString
dec esi
mov al,byte ptr
.if al!="h"    ;ignore prefix
.if al>=30h && al<=39h
sub al,30h
.elseif al>="A" && al<="F"
sub al,"A"-10  ;corrected - thx baldr
.elseif al>="a" && al<="f"
sub al,"a"-10  ;corrected - thx baldr
.else
;ignoring non hex, we'll do our best...
.continue
.endif
.if toggle==0
mov lowbits,al
mov toggle,1
.elseif toggle==1
shl al,4
or al,lowbits
mov toggle,0
mov byte ptr,al
inc edi
.endif

.endif
.endw
;check for orphaned nybble
.if toggle==1
shr al,4
or al,lowbits
mov byte ptr,al
.endif

lea edx,Val
mov eax,.QuadWord.LoDWord
mov edx,.QuadWord.HiDWord
ret
hex2qword endp

Posted on 2010-04-29 07:06:25 by Homer
Homer,

Check for trailing "h" seems to be misplaced: it can occur at any position. Also, "0x" prefix and "h" are not mutually exclusive (probably you did this on purpose?).

sub al, "A" (or "a" thereupon) converts "A" to 0, not 10 as expected by following code.
Posted on 2010-04-29 09:13:53 by baldr
What you could do is this:
or each character with 0x20.
This turns on the bit that distinguishes between upper- and lowercase, so everything becomes lowercase. Decimals can be considered 'lowercase' aswell, and are not affected.
This means you don't need a separate check for 'h' or 'H', and for 'a..f' and 'A..F', just checking for 'h' and 'a..f' is enough, and just one sub is required to handle all cases.
Posted on 2010-04-29 09:51:08 by Scali
Scali - Yeah I'll modify this function to use case flattening tomorrow, just for the warm fuzzy feeling :P
baldr - Nice catch, modified to correct this.

These are not examples of fine coding, by any means - but they might prove useful to someone at some point, if only as a learning tool.

Yeah baldr, I know they're not mutually exclusive - I'm using this for my Parser / interpreter project.. I wanted one piece of code to handle all cases, and saw no reason to implement any exclusion, given that exclusion was already enforced by the lexer stage according to my grammar rules... but even if it wasn't this code would still work (now that I've modified it to correct that bug - would you believe I was using 256 = 100h as test data? Not my best day! Hehe :) )
Posted on 2010-04-29 09:57:25 by Homer
Scali"]or each character with 0x20.
This turns on the bit that distinguishes between upper- and lowercase, so everything becomes lowercase. Decimals can be considered 'lowercase' aswell, and are not affected.


This should be done cautiously, for it can introduce funny "digits", namely DLE, DC1 and so on to EM (^P to ^Y, ASCII codes 10h...19h) if done too early. ;-)
Posted on 2010-04-29 14:08:54 by baldr