Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

how to convert big-endian numbers to native numbers delphi

I want to know how to convert big-endian numbers to native numbers in Delphi. I am porting some C++ code in that I came across:

unsigned long blockLength  = *blockLengthPtr++ << 24;
blockLength |= *blockLengthPtr++ << 16;
blockLength |= *blockLengthPtr++ << 8;
blockLength |= *blockLengthPtr;

unsigned long dataLength  = *dataLengthPtr++ << 24;
dataLength |= *dataLengthPtr++ << 16;
dataLength |= *dataLengthPtr++ << 8;
dataLength |= *dataLengthPtr;

I am not familiar with C++, so I don't understand what those operators do.

like image 465
steve0 Avatar asked Jun 17 '10 20:06

steve0


People also ask

How do you do an endian swap?

To do this, we shift the rightmost 8 bits by 24 to the left so that it becomes the leftmost 8 bits. We left shift the right middle byte by 16 (to store it as the left middle byte) We left shift the left middle byte by 8 (to store it as the right muddle byte) We finally left shift the leftmost byte by 24 to the left.

Is x86 64 big-endian?

The x86 processors use little-endian byte ordering. The least significant byte (LSB) of an integer is stored at the lowest address of the integer. The most significant byte is stored at the highest address for data items in this processor. For example, byte 7 is the most significant byte for 64-bit processors.

Is big-endian the default?

Big endian is the default byte ordering for all TCP/IP network protocols and it is not rare at all. TypedArrays are not little endian by default. They actually use the endianness of the underlying operating system.

How do you check if a number is big-endian or little endian?

If it is little-endian, it would be stored as “01 00 00 00”. The program checks the first byte by dereferencing the cptr pointer. If it equals to 0, it means the processor is big-endian(“00 00 00 01”), If it equals to 1, it means the processor is little-endian (“01 00 00 00”).


2 Answers

Andreas's answer is a pretty good example of how to do it in pure pascal, but it still looks kinda awkward, just like the C++ code. This can actually be done in a single assembly instruction, though which one depends on whether you're using 32-bit or 16-bit integers:

function SwapEndian32(Value: integer): integer; register;
asm
  bswap eax
end;

function SwapEndian16(Value: smallint): smallint; register;
asm
  rol   ax, 8
end;
like image 185
Mason Wheeler Avatar answered Oct 20 '22 00:10

Mason Wheeler


To reverse the order of the bits:

procedure SwapEndiannessOfBits(var Value: cardinal);
var
  tmp: cardinal;
  i: Integer;
begin
  tmp := 0;
  for i := 0 to 8*sizeof(Value) - 1 do
    inc(tmp, ((Value shr i) and $1) shl (8*sizeof(Value) - i - 1));
  Value := tmp;
end;

To reverse the order of the bytes:

procedure SwapEndiannessOfBytes(var Value: cardinal);
var
  tmp: cardinal;
  i: Integer;
begin
  tmp := 0;
  for i := 0 to sizeof(Value) - 1 do
    inc(tmp, ((Value shr (8*i)) and $FF) shl (8*(sizeof(Value) - i - 1)));
  Value := tmp;
end;

I think the last one is what you are looking for. Most likely there are faster and more elegant solutions, though.

Disclaimer: I might be totally wrong. I feel a bit confused at the moment. Hopefully someone else will see this question and provide a more definite answer!

like image 41
Andreas Rejbrand Avatar answered Oct 19 '22 23:10

Andreas Rejbrand