Handmade Hero»Forums»Code
vbo
Vadim Borodin
20 posts
LARGE_INTEGER and endiannes
Hey guys!

Somewhere around Day 25 of HMH Casey was using win32-defined union called LARGE_INTEGER (https://msdn.microsoft.com/en-us/...esktop/aa383713%28v=vs.85%29.aspx) to pass a 64bit integer as a pair of two 32bit integers to some win32 API like this:

1
2
3
4
uint64 sourceValue = 0x123456789ABCDEFF;
LARGE_INTEGER transformer;
transformer.QuadPart = sourceValue;
someWin32Api(transformer.LowPart, transformer.HighPart);

I don't understand why it works. If I understand endiannes concept correctly (I am not sure) it actually depends on machine endiannes what exact values LowPart and HighPart would have. Could someone please explain this?

Before this Casey was doing the very same thing like this (which makes much more sense to me):

1
2
3
4
uint64 sourceValue = 0x123456789ABCDEFF;
uint32 lowPart = (uint32)(sourceValue & 0xFFFFFFFF);
uint32 highPart = (uint32)(sourceValue >> 32);
someWin32Api(lowPart, highPart);

Are this two peaces of code identical if we take endiannes into account?

(I understand that virtually all hardware uses Little Endian this days, I just want to better understand the concept).
Mārtiņš Možeiko
2561 posts / 2 projects
LARGE_INTEGER and endiannes
On modern Windows you don't need to worry about endianess at all. It is always little endian :)

Anyway. 0x123456789ABCDEFF value in little endian is stored in memory like this:
1
FF DE BC 9A 78 56 34 12
.
That is what "transformer.QuadPart = sourceValue;" line does.
Because you can access LARGE_INTEGER as two 32-bit integers then one of them will be read from "FF DE BC 9A" bytes (first 4 bytes), and second one from "78 56 34 12" (next 4 bytes). So on little endian first 32-bit integer (low part, because little endian) will be 0x9ABCDEFF, second one (high part) will be 0x1245678.

This won't work on big endian machine. There 64-bit integer stored in memory would be reversed "12 34 56 78 9A BC DE FF". Reading two 32-bit integers from this would get you different values for low and high parts. Low would be 0x1245678 (from first 4 bytes) and high would be 0x9ABCDEFF (next 4 bytes).

Using shifts and & would fix this - because those are endian agnostic. Using second code would always get 0x1245678 as highPart, and 0x9ABCDEFF as lowPart.
vbo
Vadim Borodin
20 posts
LARGE_INTEGER and endiannes
On modern Windows you don't need to worry about endianess at all. It is always little endian
I thought it's actual CPU or something that's Little Endian or not and it has nothing to do with operating system. Or Windows uses some magic to hide actual CPU endianness from application layer? Or you can't even run Windows on Big Endian machine this days?
Mārtiņš Možeiko
2561 posts / 2 projects
LARGE_INTEGER and endiannes
It's the last one - Windows probably doesn't support big endian CPU anymore (because it doesn't need to). So no Windows application should worry about big endian.

But yes, OS doesn't hide endianess from application. It's the "feature" of CPU.
Casey Muratori
801 posts / 1 project
Casey Muratori is a programmer at Molly Rocket on the game 1935 and is the host of the educational programming series Handmade Hero.
LARGE_INTEGER and endiannes
Edited by Casey Muratori on
Yes, I believe that Windows has never supported big-endian CPUs, but I could be wrong about that. There was a MIPS version of Windows, if I'm not misremembering, but I suspect that it just put the MIPS into little-endian mode, since I believe MIPS was one of those architectures that had programmable endianness.

But, that's all ancient history at this point, so I may just be misremembering.

- Casey