Page 1 of 1
Hex To Decimal
Posted: Fri Sep 27, 2002 7:13 am
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.
Re:Hex To Decimal
Posted: Fri Sep 27, 2002 7:01 pm
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...
Re:Hex To Decimal
Posted: Sat Sep 28, 2002 6:06 am
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;
}
Re:Hex To Decimal
Posted: Sat Sep 28, 2002 7:24 am
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.
Re:Hex To Decimal
Posted: Sat Sep 28, 2002 7:52 am
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.
Re:Hex To Decimal
Posted: Sat Sep 28, 2002 10:53 am
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
Re:Hex To Decimal
Posted: Sat Sep 28, 2002 11:43 am
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);
}
Re:Hex To Decimal
Posted: Sun Sep 29, 2002 7:38 am
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.
Re:Hex To Decimal
Posted: Sun Sep 29, 2002 8:08 am
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;)
Re:Hex To Decimal
Posted: Sun Sep 29, 2002 8:44 am
by PlayOS
Um... What do you mean?
My OS is PMode and v86 will not help my situation.
Thanks anyway, I guess....