Hex To Decimal

Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
Post Reply
PlayOS

Hex To Decimal

Post by PlayOS »

Hi,

Does anyone here know a procedure to convert hex to decimal and display it?

Also, I want to be able to write a second stage loader in C, but it must be 16bit code because I want to access BIOS Interrupts. How is this done in gcc. I want to be able to compile as binary.

Thanks.
gonchuki

Re:Hex To Decimal

Post by gonchuki »

well, that's a simple thing... but my explanation may be a bit confusing :-\
assuming that you have an array filled with the ASCII code of each digit of your hex number, this would be an example in C:

for (i = 0; i < length_of_your_number; i++) {
hex_value += (((ascii_array % 64) + 9) % 57) * 16 ^ (length_of_your_number - i);
}

this was assuming that hex letters are in upper-case, so if you have something like f30b you should change the 64 for a 96... well, you could also add an IF inside the loop to check whether the letter is upper or lower case...

well, i hope this works since i did the translation on the fly from a Visual Basic version of the code... :o :o :o
Tim

Re:Hex To Decimal

Post by Tim »

Better:

Code: Select all

unsigned long hex_to_num(const char *str)
{
    unsigned long num;

    while (*str != '\0')
    {
        num <<= 4;
        if (*str >= '0' && *str <= '9')
            num |= *str - '0';
        else if (*str >= 'a' && *str <= 'F')
            num |= *str - 'a;
        else if (*str >= 'A' && *str <= 'F')
            num |= *str - 'F';
        else
            return 0;
    }

    return num;
}
PlayOS

Re:Hex To Decimal

Post by PlayOS »

Thanks for the code, it is helpful for other purposes, but not what I was hoping for. I will explain better.

OK, I want to be able to display a decimal number on the screen. Say I have the hex value 0x10, I want to be able to display on the screen 16 the decimal value of the hex. The functions you have supplied (thankyou :)) will return the number, however this basically leaves me in the same way as before, what I need is to convert the hex to a string representation of the decimal. So 0x10 would become '16', null terminated of course.

Thanks for the help so far. :D
PlayOS

Re:Hex To Decimal

Post by PlayOS »

OK, I knew I had this lying around somewhere. It is a function that accepts a char* and an unsigned int, the char* is a pointer to a buffer to recieve the string form of a number, the unsigned int is the number to be put in the string.

I will be attempting to convert this to asm and I will post here if and when I get it done, but until then if anyone wants to have a go at converting this into NASM syntax asm, please feel free to do so. If I manage to do it I will post the code here for others to use but I might not even be able to do it, so if someone can I would appreciate it. This function only handles positive values, I know how to make it accept either, but I can do this, I just need help with the conversion to asm.

Here is the code:

//============================================
void Num2Str( char* cString_, unsigned int nNum_ )
{
   unsigned int nCounter = 1000000000;
   int nCharPos = 0;
   unsigned int nDecrement = nNum_;
   
   if ( nNum_ == 0 )
   {
      cString_[ 0 ] = '0';
      cString_[ 1 ] = '\0';
      return;
   }

   while ( nCounter > 0 )
   {
      if ( nNum_ >= nCounter )
      {
         cString_[ nCharPos ] = ( char )( ( nDecrement / nCounter ) + 48 );
         nDecrement -= ( ( nDecrement / nCounter ) * nCounter );
         nCharPos++;
      }
      nCounter /= 10;
   }

   cString_[ nCharPos ] = '\0';
}
//============================================

thanks.
dronkit

Re:Hex To Decimal

Post by dronkit »

i did this code to be able to dump register values in my os. it could be useful to you, however, it 16 bits, will only print via BIOS and only hex values. you can combine with "tim robinson"s code.


/*
* Shows a 16-bit word to console. Need word to dump in% dx.
*/
HexTable:      .ascii "0123456789ABCDEF"
show_16bit_word:
   pushw %bx
   pushw %ax
   movw $HexTable, %bx
   movw %dx, %ax
   /* Do higher 4 bits from higher byte */
   andb $0xf0, %ah
   shr $0x4, %ah
   xchg %ah, %al
   xlat
   call dochar
   movw %dx, %ax
   /* Do lower 4 bits from higher byte */
   andb $0xf, %ah
   xchg %ah, %al
   xlat
   call dochar
   movw %dx, %ax
   /* Do higher 4 bits from lower byte */
   andb $0xf0, %al
   shr $0x4, %al
   xlat
   call dochar
   movw %dx, %ax
   /* Do lower 4 bits from lower byte */
   andb $0xf, %al
   xlat
   call dochar
   popw %ax
   popw %bx
   ret
Tim

Re:Hex To Decimal

Post by Tim »

Code: Select all

/* str must be at least 9 chars long */
void str_to_hex(char *str, unsigned long num)
{
    static char hexdigits[] = "0123456789abcdef";
    char str[9], *ptr;

    ptr = str + 9;
    *ptr = '\0';
    do
    {
        ptr--;
        *ptr = hexdigits[num % 16];
        num >>= 4;
    } while (num > 0);
}
PlayOS

Re:Hex To Decimal

Post by PlayOS »

OK, Here is the C/C++ Code again:

void Num2Str( char* cBuf_, unsigned int nNum_ )
{
   unsigned int nCounter = 1000000000;
   int nCharPos = 0;
   unsigned int nDecrement = nNum_;
   
   if ( nNum_ == 0 )
   {
      cBuf_[ 0 ] = '0';
      cBuf_[ 1 ] = '\0';
      return;
   }

   while ( nCounter > 0 )
   {
      if ( nNum_ >= nCounter )
      {
         cBuf_[ nCharPos ] = ( char )( ( nDecrement / nCounter ) + 48 );
         nDecrement -= ( ( nDecrement / nCounter ) * nCounter );
         nCharPos++;
      }
      nCounter /= 10;
   }

   cBuf_[ nCharPos ] = '\0';
}

Here is the Asm Code:

_Num2Str:
   push   ebp
   mov      ebp, esp
   add      esp, 8                     ; Create Local Storage
   mov      dword [ebp - 8], 1000000000      ; Initialize nCounter
   mov      ecx, dword [ebp + 8]         ; Copy nNum_
   mov      dword [ebp - 4], ecx         ; Initialize nDecrement
   mov      ebx, dword [ebp + 12]         ; Copy cBuf_
   cmp      ecx, 0                     ; Compare nNum_ to Zero
   jne      .CounterLoop               ; nNum_ is not Zero
   mov      byte [ebx], '0'               ; Set cBuf_ to '0'
   mov      byte [ebx + 1], 0            ; Zero terminate cBuf_
   mov      esp, ebp                  ; Restore ESP
   pop      ebp                        ; Restore EBP
   ret      8                        ; Return and clean the stack
.CounterLoop:
   mov      eax, dword [ebp - 8]         ; Copy nCounter
   cmp      eax, 0                     ; Compare nCounter to Zero
   jne      .CounterIsValid               ; nCounter is above Zero
   mov      byte [ebx], 0               ; Zero terminate cBuf_
   mov      esp, ebp                  ; Restore ESP
   pop      ebp                        ; Restore EBP
   ret      8                        ; Return and clean the stack
.CounterIsValid:
   cmp      ecx, eax                  ; Compare nNum_ to nCounter
   jge      .IsValidDigit               ; nNum_ >= nCounter
   mov      edx, 10                     ; Divisor
   div      edx                        ; EAX = nCounter / 10
   mov      dword [ebp - 8], eax         ; Save new nCounter value
   jmp      short .CounterLoop            ; Process next digit
.IsValidDigit:
   mov      eax, dword [ebp - 4]         ; Copy nDecrement
   mov      edx, dword [ebp - 8]         ; Copy nCounter
   div      edx                        ; EAX = nDecrement / nCounter
   mov      edx, eax                  ; Save nDecrement / nCounter
   add      eax, 48                     ; EAX = Digit Ascii Code
   mov      byte [ebx], al               ; Store the Digit
   inc      ebx                        ; Increment cBuf_ Address
   mov      eax, edx                  ; Put nDecrement / nCounter in EAX
   mov      edx, dword [ebp - 8]         ; Copy nCounter
   mul      edx                        ; EAX = (nDecrement / nCounter) * nCounter
   mov      edx, dword [ebp - 4]         ; Copy nDecrement
   sub      edx, eax                  ; EDX = nDecrement - ((nDecrement / nCounter) * nCounter)
   mov      dword [ebp - 4], edx         ; Save new nDecrement value
   mov      eax, dword [ebp - 8]         ; Copy nCounter
   mov      edx, 10                     ; Divisor
   div      edx                        ; EAX = nCounter / 10
   mov      dword [ebp - 8], eax         ; Save new nCounter value
   jmp      .CounterLoop               ; Process next digit


This asm code causes a divide error (#DE) exception when I attempt to use it. Could someone have a look and tell me what the problem is? If you read my previous posts in this topic you will see what I am trying to do.

Thanks.
Tom

Re:Hex To Decimal

Post by Tom »

I'd be better to program you OS PMode 32/bit - and use v86.

That way, your OS is up to date & fast;)
PlayOS

Re:Hex To Decimal

Post by PlayOS »

Um... What do you mean?

My OS is PMode and v86 will not help my situation.

Thanks anyway, I guess....
Post Reply