What is the purpose of segment registers in x86 protected mode?
I need to modify some dll, but i don't know, what excatly does segment registers (DS
, SS
, ...) in protected mode. I learned in school about real 16-bit mode, where segment registers multiply by 16 plus offset in normal register gives effective address in physical memory. In protected mode, there is some flat memory model and virtual memory, where each process "has" 4GB memory, so if registers have 32-bit, then i can address each byte of virtual memory only by "offset" register. So which puproses have segment registers in protected mode, for example
mov eax, dword ptr ds:[20037DA0]
Some historical background
The 8086 always used a fixed 64KiB Window per segment whose starting address was calculated by (segment register * 16). Since the 80286 there are some special tables in memory (GDT and LDT). These tables contain the starting address, the length and the access rights of a segment. The segment registers (CS, DS, ES, SS - and since 80386: FS, GS) contain indexes into these tables.
So theoretically an operating system may set the offset and the length of a segment in a way it wants to do that: On 8086 DS=0x0123 means: Segment is 64KiB starting from address 0x01230. In 32-bit mode DS=0x0123 may mean: Segment start at address 0xABCD, length is 0xEF bytes - this depends on the content of the GDT and LDT tables created by the operating system. Trying to access a segment outside this range (DS:0x1000 if the length is < 0x1000) will cause an exception (interrupt).
Current situation
However most modern 32-bit operating systems do not really use segment registers any more. Their values are set depending on the mode (kernel or user) because of access rights issues. The starting address is typically 0 and the length is 4GiB.
The real memory protection is done using the MMU so that some areas of memory cannot be accessed in user mode. In modern operating systems the MMU is absolutely essiential. It maps an "absolute" virtual address to a real physical address checking for access right violations.
There is one exception: Some operating systems (Windows and Linux for example) use the FS and/or GS segments to really point to a different memory area.
For this reason in 64-bit mode the x86 processors use the CS register only for access rights issues and FS and GS can be used to add an offset to each address. As far as I know DS, ES and SS are not used while the content of the registers FS and GS does not matter but there are special registers that explicitly give the offset to be added to an operation that uses FS or GS.
Basicaly the purpose is the same as in real mode except the way they work is slightly different. DS in your example selects one memory descriptor in your GDT(google this term if you really wanna understand this, "Global descriptor table") which contains information like base address, end address, granularity etc. Your offset is then added to the base address, the end. If you are on windows (i bet on linux its the same) you dont generaly have to worry about these segment registers, as you said its flat model, that means there should be only one descriptor for all the memory, so if you dont change these registers it should work as if they werent even existing.
I'll give you a simple answer, but for further information I recommend the link below to AMD's architecture documents, very easy reading. PS: I haven't covered Xeon or PAE here..
IA-32 (x86) architecture has a 32bit physical address bus for RAM.
The 32bit bus is further split into 2x 16bits segments each one capable of accessing 2GB of RAM a total of 4GB.
This is called memory bank switching.
In order to allow protection Intel along with MS decided to use one segment for kernelmode and the other for usermode - which is why Windows historically had a 2GB usermode address space. It's an x86 hardware limitation, not a Windows limitation.
The segment registers separated kernel space and userspace addresses. That's how memory protection was implemented.
Furthermore IA-32 general had 32bit internal registers as well, so it couldn't page. This is real mode (no address translation).
Paging requires 36bits I think (don't quote me ) that's where IA32e came in. The extra bits on IA-32e allowed paging from the HDD, this is the only way it could run on x64 Windows since x64 requires NX and it's located at bit 63.
Please read the AMD architecture documents, personally I find them more informative than the Intel versions.
http://developer.amd.com/wordpress/media/2012/10/24593_APM_v21.pdf
PS with AMD64 flat memory was introduced, doing away with segments.
However 32bit processes still need segment registers. On AMD64 when a 32bit process hits top of stack a pointer is thrown to a base address on a new segment register. This way 32bit apps can effectively eat as much RAM as they want, no limit. Well within reason ofc...:)
Hope this helps.