• Welcome to Valhalla Legends Archive.
 

Okay, so I'm not so good at C as I thought..

Started by tA-Kane, February 14, 2003, 08:06 PM

Previous topic - Next topic

tA-Kane

I'm trying to create a C function to do a byteswap (change endianness) of an integer...

But my compiler keeps giving me errors, or, when it doesn't give errors, the results of the test aren't as expected...

Here's the code which I *think* should work, but (perhaps painfully obviously) does not.

Could you tell me what I'm doing wrong? (I don't want the fix, I'd like to get that myself, if I could.)
unsigned long ByteSwap(unsigned long Value){
 char *Buffer, *Temp;
 unsigned long* rVal;
 rVal[0] = Value;
 Temp = (char*)rVal[0];
 Buffer[0] = Temp[3];
 Buffer[1] = Temp[2];
 Buffer[2] = Temp[1];
 Buffer[3] = Temp[0];
 rVal = (unsigned long*)Buffer;
 return rVal[0];
}

int main(void){
  unsigned long a, b;
  a = 0x1246578lu
  b = ByteSwap(a);
  printf("%x %x",a,b);
  return 0;
}

(I'm trying to get the printf to display 12345678 and then 78563412.)
Macintosh programmer and enthusiast.
Battle.net Bot Programming: http://www.bash.org/?240059
I can write programs. Can you right them?

http://www.clan-mac.com
http://www.eve-online.com

Zonker

only a couple mistakes in ByteSwap:
unsigned long ByteSwap(unsigned long Value) {
      char Buffer[4], *Temp;
      unsigned long* rVal;
      rVal = &Value;
      Temp = (char*)rVal;
      Buffer[0] = Temp[3];
      Buffer[1] = Temp[2];
      Buffer[2] = Temp[1];
      Buffer[3] = Temp[0];
      rVal = (unsigned long*)Buffer;
      return (unsigned long )*rVal;
}
You tried to assign values to the Buffer pointer when it hadn't been initialized to anything, so just made it an array.  rVal wasn't initialized either, so i just set it to the address of Value.  That should work perfectly (If you fix the value of a in main ;))

I was bored and wrote a similiar function in asm that is about 9 times faster on my machine if you want it (not the best code, i'm a bit rusty :():
unsigned long MySwap(unsigned long *Value) {
      __asm {
            mov edi, Value                  
            mov ax, word ptr [edi]
            mov bh, al
            mov bl, ah
            mov ax, word ptr [edi+2]
            mov edx, 0
            mov dh, al
            mov dl, ah
            mov ax, bx
            mov cx, 0x08
            shl eax, cl
            shl eax, cl
            mov ax, dx
      }
}

Skywing

#2
Quoteonly a couple mistakes in ByteSwap:
unsigned long ByteSwap(unsigned long Value) {
      char Buffer[4], *Temp;
      unsigned long* rVal;
      rVal = &Value;
      Temp = (char*)rVal;
      Buffer[0] = Temp[3];
      Buffer[1] = Temp[2];
      Buffer[2] = Temp[1];
      Buffer[3] = Temp[0];
      rVal = (unsigned long*)Buffer;
      return (unsigned long )*rVal;
}
You tried to assign values to the Buffer pointer when it hadn't been initialized to anything, so just made it an array.  rVal wasn't initialized either, so i just set it to the address of Value.  That should work perfectly (If you fix the value of a in main ;))

I was bored and wrote a similiar function in asm that is about 9 times faster on my machine if you want it (not the best code, i'm a bit rusty :():
unsigned long MySwap(unsigned long *Value) {
      __asm {
            mov edi, Value                  
            mov ax, word ptr [edi]
            mov bh, al
            mov bl, ah
            mov ax, word ptr [edi+2]
            mov edx, 0
            mov dh, al
            mov dl, ah
            mov ax, bx
            mov cx, 0x08
            shl eax, cl
            shl eax, cl
            mov ax, dx
      }
}
There's absolutely no need for all of that.
__asm {
    bswap
}

iago

#3
Nice ruining all the fun! :-)
This'll make an interesting test for broken AV:
QuoteX5O!P%@AP[4\PZX54(P^)7CC)7}$EICAR-STANDARD-ANTIVIRUS-TEST-FILE!$H+H*


Yoni

#4
QuoteThere's absolutely no need for all of that.
__asm {
    bswap
}
But that's 486+ only!

tA-Kane

#5
Quoteunsigned long ByteSwap(unsigned long Value) {
      char Buffer[4], *Temp;
      unsigned long* rVal;
      rVal = &Value;
      Temp = (char*)rVal;
      Buffer[0] = Temp[3];
      Buffer[1] = Temp[2];
      Buffer[2] = Temp[1];
      Buffer[3] = Temp[0];
      rVal = (unsigned long*)Buffer;
      return (unsigned long )*rVal;
}

If rVal was declared as unsigned long (instead of unsigned long*), why doesn't this work:
 Temp = (char*)&Value;
  //do byteswap
  rVal = (unsigned long)Buffer;
  return rVal;
?

Instead of getting the byteswapped value, I get a different value, which I *think* is the address of Value (perhaps the address after a byteswap).
Macintosh programmer and enthusiast.
Battle.net Bot Programming: http://www.bash.org/?240059
I can write programs. Can you right them?

http://www.clan-mac.com
http://www.eve-online.com

Banana fanna fo fanna

#6
Skywing you loser, he programs on PowerPC.

Ickypoopy

Why not just
printf("%c%c%c%c", Buffer[3], Buffer[2], Buffer[1], Buffer[0]);or
wsprintf(Temp, "%c%c%c%c", Buffer[3], Buffer[2], Buffer[1], Buffer[0]);instead of going thru all that trouble?

tA-Kane

#8
I don't particularly like using printf (or any variant thereof) for something like that...

IMO, printf should be used for something user-readable.

I have nothing else nice to say about printf for a byteswap.
Macintosh programmer and enthusiast.
Battle.net Bot Programming: http://www.bash.org/?240059
I can write programs. Can you right them?

http://www.clan-mac.com
http://www.eve-online.com

Skywing

QuoteSkywing you loser, he programs on PowerPC.
I was replying to Zonker's unnecessarily complicated function.

There are lots of ways you could swap the bytes of something - I'd recommend either directly using bitwise operations to do it, or defining something like so:

union {
    DWORD Bits;
    struct {
          BYTE B0;
          BYTE B1;
          BYTE B2;
          BYTE B3;
    };
};

You could easily swap the bytes of something by manipulating the members of the structure, which seems to be what you were aiming to do with your function.

Anyways, if you're still having trouble, these are some functions (not particularly great; they'd be better as macros IMO, and they use addition instead of bitwise-OR (?!) but...) which might help, from the VC7 CRT source code:

/***
*rotl.c - rotate an unsigned integer left
*
*       Copyright (c) 1989-2001, Microsoft Corporation. All rights reserved.
*
*Purpose:
*       defines _byteswap() - performs a byteswap on an unsigned integer.
*
*******************************************************************************/

#include <cruntime.h>
#include <stdlib.h>

#ifdef _MSC_VER
#pragma function(_byteswap_ulong, _byteswap_uint64, _byteswap_ushort)
#endif  /* _MSC_VER */

/***
*unsigned long _byteswap_ulong(i) - long byteswap
*
*Purpose:
*       Performs a byte swap on an unsigned integer.
*
*Entry:
*       unsigned long i:        value to swap
*
*Exit:
*       returns swaped
*
*Exceptions:
*       None.
*
*******************************************************************************/


unsigned long __cdecl _byteswap_ulong(unsigned long i)
{
    unsigned int j;
    j =  (i << 24);
    j += (i <<  8) & 0x00FF0000;
    j += (i >>  8) & 0x0000FF00;
    j += (i >> 24);
    return j;
}

unsigned short __cdecl _byteswap_ushort(unsigned short i)
{
    unsigned short j;
    j =  (i << 8) ;
    j += (i >> 8) ;
    return j;
}

unsigned __int64 __cdecl _byteswap_uint64(unsigned __int64 i)
{
    unsigned __int64 j;
    j =  (i << 56);
    j += (i << 40)&0x00FF000000000000;
    j += (i << 24)&0x0000FF0000000000;
    j += (i <<  8)&0x000000FF00000000;
    j += (i >>  8)&0x00000000FF000000;
    j += (i >> 24)&0x0000000000FF0000;
    j += (i >> 40)&0x000000000000FF00;
    j += (i >> 56);
    return j;

}

Banana fanna fo fanna

#10
QuoteI was replying to Zonker's unnecessarily complicated function.

A likely story.