Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations strongm on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Converting Hex to Int

Status
Not open for further replies.
Nov 20, 2004
1
US
I need help converting a hex to. I'm getting core dumps while compiling under Linux. Any help would be greatly appreciated!

This is the C code
Code:
unsigned int HexToInt(char *theString)
{
unsigned int value = 0;
char temp;
while(*theString != '\0')
{
value *= 16; /* peel off right digit */
if (*theString <= '9')
temp = *theString & 0x0f;
else /* convert ascii to int */
{
temp = *theString & 0x0f;
temp = temp + 9;
}
value += (int) temp;
theString++;
}
return value;
}

This is what I have so far for my Assembly language
Code:
ptr =-8
value =-4
strPtr =8

        .text
        .globl  hexToInt
hexToInt:
        pushl   %esp
        movl    %esp, %ebp
        addl    $ptr, %esp
        movl    $0, value(%ebp)
        movl    strPtr(%ebp), %eax
        movl    %eax, ptr(%ebp)

loop:
        movl    ptr(%ebp), %eax
        cmpb    $0, (%eax)
        je      allDone

        cmpb    $'9', (%eax)
        jle     temp1

        addl    $0x0f, %eax
        addl    $0x9, %eax

        shll    $4, value(%ebp)
        addl    %eax, value(%ebp)
        incl    ptr(%ebp)
        jmp     loop
temp1:
        addl    $0x0f, %eax
        addl    %eax, value(%ebp)
        incl    ptr(%ebp)
        jmp     loop



allDone:
        movl    value(%ebp), %eax
        movl    %ebp, %esp
        popl    %ebp
        ret
 
Here's some nasm code. Tested and everything.
Couldn't understand why you would use jumps inside the loop when they're unecessary.

BITS 32

SEGMENT _TEXT ALIGN=4 PUBLIC USE32 CLASS=CODE

GLOBAL _HexToInt
align 4
_HexToInt:
; edx is string pointer
; eax is final integer
; ebx is used for calculations

push ebx ; save used registers
push edx

xor eax, eax ; clear final integer
mov edx, [esp+12] ; get string pointer

jmp scanchar ; jump to bottom of loop in case NIL char.

mainloop:

xor bh, bh ; clear temp value
cmp bl, 58 ; if hex char is 'A' or above, carry will be clear
cmc ; flip carry
rcl bh, 4 ; if hex char is above 9, bh=8. bh=0 otherwise.
sub bh, 1 ; chars 'A' - '9' is 7, not 8, so sub 1
adc bh, 0 ; if bh WAS 0, then adc will return it to 0.
sub bl, bh ; substract 7 from hex digit if 'A' or above.
sub bl, 48 ; substract '0' from char to get integer value.

shl eax, 4 ; multiply integer by 16
or al, bl ; add hex integer value.

scanchar:

mov bl, [edx] ; grab next character
inc edx ; increment string pointer
test bl, bl ; check if zero
jne mainloop ; if not zero, continue loop

pop edx
pop ebx
ret

end

**********
Basically, the algorithm brings down the values of 'A' to 'F' down by 7, so that all values are contiguous from 48 to 63. Then you can just substract 48 and get your value.

The way we do this is comparing the ascii value with 58. This will set the carry depending on if it's greater than or less than. What we want is the carry bit to be set when it's above 58. We can then use the carry bit with 'rcl bh, 4' to create the value of 8. Otherwise, it's zero.

But when we do the compare, the carry bit is the opposite of what we want it. That's why we flip it with 'cmc'.

Now we have the value 8 if the ascii value is 'A' to 'F'. But we need to substract 7, not 8.

So we substract 1. This is fine for 'A' to 'F', but if it's '0' to '9', we now have -1 in bh. But luckily, in this case, the carry bit would be set and we add the carry with 'adc bh, 0' to bring it back up to 0. If bh is 7, the last command will do nothing since the carry bit won't be set. So we're good to go.

Now bh will either contain 7 if ascii value is 'A' to 'F' or 0 if '0' to '9'. So we substract bh from bl and now we have a value in the contiguous range of 48 to 63.

All that's left is substracting 48 and you've got your integer value without using a single jump.


Here's an example of two different values.
Let's try 5 and B.
First 5 which is ascii 53, so bl = 53 dec

xor bh, bh ; bh = 0
cmp bl, 58 ; 53<58, so carry=1
cmc ; carry=0
rcl bh, 4 ; bh = 0
sub bh, 1 ; bh = -1, but 0<1 so carry=1
adc bh, 0 ; bh = -1(bh) + 0 + 1(carry) = 0
sub bl, bh ; bl = 53(bl) - 0(bh) = 53
sub bl, 48 ; bl = 53(bl) - 48 = 5

So bl is 5 just as expected.

Now let's try 'B' which is 66 dec. so bl = 66 dec.

xor bh, bh ; bh = 0
cmp bl, 58 ; 66>58, so carry=0
cmc ; carry=1
rcl bh, 4 ; bh = 8
sub bh, 1 ; bh = 7, and 8>1 so carry=0
adc bh, 0 ; bh = 7(bh) + 0 + 0(carry) = 7
sub bl, bh ; bl = 66(bl) - 7(bh) = 59
sub bl, 48 ; bl = 59(bl) - 48 = 11

So bl is 11='B' just as expected.

No jumps. Sure there's lots of register contention, but that's not nearly as bad as all those branches.

Have fun



A programmer is a device for converting Coke into software.
 
Shouldn't your first line read:

pushl %ebp

and not

pushl $esp

 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top