Printing hex numbers

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.
exkor
Member
Member
Posts: 111
Joined: Wed May 23, 2007 9:38 pm

Post by exkor »

http://www.wasm.ru/forum/viewtopic.php?id=20503
posts # 8,15,...
post # is at the top right corner of post header

bewing, you really need to get rid of those calls, I hope they are not far calls.
far call instruction: http://www.agner.org/optimize/ (10+ times slower plus call itself is not fast instruction0
User avatar
JamesM
Member
Member
Posts: 2935
Joined: Tue Jul 10, 2007 5:27 am
Location: York, United Kingdom
Contact:

Post by JamesM »

What a useful post! If only I spoke russian...
exkor
Member
Member
Posts: 111
Joined: Wed May 23, 2007 9:38 pm

Post by exkor »

russian is not required, each peace of code is less than 40 baits in size, but if you don't know assembly - there is nothing there to do probably.
and the 2nd link is extremely important. ALL Read.

http://www.asmcommunity.net/board/ , search for "hex" and you'll find lots of hex related function, not each of them is state of the art but some better than C/C++
User avatar
JamesM
Member
Member
Posts: 2935
Joined: Tue Jul 10, 2007 5:27 am
Location: York, United Kingdom
Contact:

Post by JamesM »

exkor wrote:russian is not required, each peace of code is less than 40 baits in size, but if you don't know assembly - there is nothing there to do probably.
and the 2nd link is extremely important. ALL Read.

http://www.asmcommunity.net/board/ , search for "hex" and you'll find lots of hex related function, not each of them is state of the art but some better than C/C++
I do know assembly, I just found all the explanations being in an eastern bloc language a little confusing!!! ;)
User avatar
bewing
Member
Member
Posts: 1401
Joined: Wed Feb 07, 2007 1:45 pm
Location: Eugene, OR, US

Post by bewing »

exkor, they are near calls, of course -- there has been no good reason for anyone to ever use a far call for the last 10 years. But, you are right, I had never gotten around to optimizing this pair of routines. So, better code:

Code: Select all

dhex_lng:
	ror ecx, 16			; swap the high & low words of ecx
dhex_s:
	push edx
	mov edx, ecx
	movzx ecx, ch			; convert high byte to 2 hex digits + 2 attrib bytes
	mov cx, [hex_lkup + ecx*2]		; get 2 bytes from lookup table
	mov al, cl				; high digit
	; Note: the high digit is supposed to be written 1st, so it ends up in dl
	stosw
	mov al, ch				; low digit
	stosw					; attrib was still in ah
	movzx ecx, dl			; now the low byte of input ecx
	mov cx, [hex_lkup + ecx*2]		; get 2 bytes from lookup table
	mov al, cl				; high digit
	stosw
	mov al, ch				; low digit
	stosw					; attrib still in ah
	mov ecx, edx
	pop edx
	ret
User avatar
XCHG
Member
Member
Posts: 416
Joined: Sat Nov 25, 2006 3:55 am
Location: Wisconsin
Contact:

Post by XCHG »

I am not a C programmer but I did two macros that simulate ROL and ROR in C:

Code: Select all

#define ROL(Value, Times) Value = ((Value << Times) | Value >> ((sizeof(Value) << 0x03) - Times))
#define ROR(Value, Times) Value = ((Value >> Times) | Value << ((sizeof(Value) << 0x03) - Times))
On the field with sword and shield amidst the din of dying of men's wails. War is waged and the battle will rage until only the righteous prevails.
User avatar
JamesM
Member
Member
Posts: 2935
Joined: Tue Jul 10, 2007 5:27 am
Location: York, United Kingdom
Contact:

Post by JamesM »

I am not a C programmer but I did two macros that simulate ROL and ROR in C:

Code: Select all

#define ROL(Value, Times) Value = ((Value << Times) | Value >> ((sizeof(Value) << 0x03) - Times)) 
#define ROR(Value, Times) Value = ((Value >> Times) | Value << ((sizeof(Value) << 0x03) - Times))
A better version:

Code: Select all

int rol(int value, int times)
{
  asm volatile("rol %0, %1" : "=a" (value) : "a" (value), "r" (times));
  return value;
}
int ror(int value, int times)
{
  asm volatile("ror %0, %1" : "=a" (value) : "a" (value), "r" (times));
  return value;
}
Ph33r! And with code inlining the calls get taken out. Much faster than three shifts, an OR and a subtract!
User avatar
XCHG
Member
Member
Posts: 416
Joined: Sat Nov 25, 2006 3:55 am
Location: Wisconsin
Contact:

Post by XCHG »

JamesM,

Of course that's better. But then again, that's not C. Oh by the way, this is another Hexadecimal printing function that I wrote today in VC++. With this one, you can specify the number of nibbles that have to be printed and the value will be adjusted according to the number of nibbles that have to be printed.

Code: Select all

void WriteHex (unsigned int InValue, unsigned int NumberofNibblesToPrint = (sizeof(unsigned int) << 0x01), 
               bool IncludeHexPrefix = true) {
  
  /* Exit the function if the number of nibbles to print is zero */
  if (NumberofNibblesToPrint == 0)
    return;

  /* Print the "0x" hexadecimal value prefix if requested */
  if (IncludeHexPrefix == true)
    printf("0x");
  
  /* If the number of  nibbles requested to be printed is more than the number of nibbles available
     in the [InValue] parameter, then set the maximum number of nibbles to the number of nibbles
     available in this parameter */
  if (NumberofNibblesToPrint >  (sizeof(InValue) << 0x01))
    NumberofNibblesToPrint = (sizeof(InValue) << 0x01);

  /* Now get the requested nibble and the nibbles to its right (if any) to the leftmost nibble of
     the value so that they can be easily extracted */
  InValue = InValue << ((sizeof(InValue) << 0x03) - (NumberofNibblesToPrint << 0x02));
  
  /* Create a acharacter buffer to take care of printing a nibble at a time */
  char CurrentChar;

  /* While there are still nibbles to be printed ... do these */
  while (NumberofNibblesToPrint-- > 0) {

    /* Get the leftmost nibble in the [CurrentChar] variable */
    CurrentChar = (char) ((InValue & 0xF0000000) >> 28) & 0x0F;

    /* If the nibble is more than 9, then it should be a character between 'A' to 'F' */
    if (CurrentChar > 9)
      CurrentChar += 7;

    /* Convert the current nibble to its equivalent character */
    CurrentChar += 48;
    
    /* Print the current nibble */
    printf("%c", CurrentChar);

    /* Get the next nibble to the leftmost nibble in the value */
    InValue = InValue << (sizeof(char) << 0x02);
  } /* while (NumberofNibblesToPrint-- > 0) { */

}
On the field with sword and shield amidst the din of dying of men's wails. War is waged and the battle will rage until only the righteous prevails.
User avatar
JamesM
Member
Member
Posts: 2935
Joined: Tue Jul 10, 2007 5:27 am
Location: York, United Kingdom
Contact:

Post by JamesM »

XCHG wrote:JamesM,

Of course that's better. But then again, that's not C.
It doesn't matter what it's implemented in, it can be called from C and that's the main point. How do you think inb() and outb() are implemented normally? ;)
User avatar
os64dev
Member
Member
Posts: 553
Joined: Sat Jan 27, 2007 3:21 pm
Location: Best, Netherlands

Post by os64dev »

JamesM wrote:
XCHG wrote:JamesM,

Of course that's better. But then again, that's not C.
It doesn't matter what it's implemented in, it can be called from C and that's the main point. How do you think inb() and outb() are implemented normally? ;)
As Memory Mapped IO on a MIPSboard?

I would use the C function (maybe a templated inline version) anytime because at -O3 gcc translates is to a single rol and ror. Any it still would be portable across platforms.
Author of COBOS
User avatar
JamesM
Member
Member
Posts: 2935
Joined: Tue Jul 10, 2007 5:27 am
Location: York, United Kingdom
Contact:

Post by JamesM »

os64dev: After a quick test I discovered you're right. I had no idea GCC could optimise that well! I retract my statement.
Post Reply