Remix.run Logo
geon 3 days ago

Is this only relevant to real mode, or is it still in use in protected mode and/or x64?

Dwedit 3 days ago | parent [-]

On 32-bit Windows, segmentation registers still exist, but they are almost always set to zero. CS (code segment), DS (data segment), ES (extra segment), and SS (stack segment) are all set to zero. But FS and GS are used for other purposes.

For a 32-bit program, FS is used to point to the Thread Information Block (TIB). GS is used to point to thread-local storage since after Windows XP. Programs using GS for thread-local storage won't work on prior versions of Windows (they'll just crash on the first access).

X64 made it even more formal that CS, DS, SS and ES are fixed at zero. 32-bit programs running on a 64-bit OS can't reassign them anymore, but basically no programs actually try to do that anyway.

---

As for shorter types of pointers being in use? Basically shorter pointers are only used for things relative to the program counter EIP, such as short jumps. With 32-bit protected mode code, you can use 32-bit pointers and not worry about 64K-size segments at all.

---

Meanwhile, some x64 programs did adopt a convention to use shorter pointers, 32-bit pointers on a 64-bit operating system. This convention is called x32, but almost nobody adopted it.

rep_lodsb 3 days ago | parent | next [-]

It's quite possible to write a program that uses 32-bit pointers in 64-bit mode, just keep all code and data at addresses below 4G. Such a program will run on any standard x86-64 kernel, because it doesn't use the x32 ABI. x32 is "only" required to support the C library, which expects pointers passed from/to the kernel to be the same size as those in userland.

(Things THEY don't want you to know: you can in fact write code in languages which aren't C, don't compile down to C, and don't depend on a C library. Even under Linux.)

As for reloading segment registers, 64-bit Linux is able to run 32-bit binaries, so there have to be ring 3 code segments for both modes. And there is nothing in the architecture stopping assembly code from jumping between those segments!

With a 32-bit binary that does this, you get access to all the features of 64-bit mode, with everything in your address space guaranteed to be mapped at an address below 4G. The only point where you need to use 64-bit pointers is in structures passed to syscalls. (for arguments in registers it's done automatically by zero-extension)

xxs 3 days ago | parent | prev [-]

>some x64 programs did adopt a convention to use shorter pointers, 32-bit pointers on a 64-bit operating system.

It's doable in managed languages, e.g. Java has compressed pointers by default on sub 32GB heaps. I suppose it's doable even in C alike setup (incl OS calls) but that would require wrappers to bit shift the pointers on each dereference (and passive to the OS, extern)

gpderetta 2 days ago | parent [-]

both GCC and the linux kernel support x32 directly. Distros even shipped system libraries compiled for x32.

There was no uptake and I believe it is deprecated today.

xxs 2 days ago | parent [-]

With x32 the limit would be 4GB which is on the low side of things. Having 8byte alignment (i.e. last 3 bits zero), allows for 32GB - which is better.

gpderetta 2 days ago | parent [-]

That would work in Java. In C is a bit complicated as you can have pointers with byte granularity. In principle the size of a pointer need not be the same for all types: you can have char, short, int and float pointers be 64 bits and everything else be 32 bits. (void has to be 64 bit as well as you must be able to round trip through it). I suspect that would break 90% of code out there though.