The past few weeks i've been working on building a 64 bit kernel and converting my OS to long mode. When using long mode and then for example doing a far transfer to a 32 bit code segment, which for example we will say has DS set to a segment limit of FFFFFF (so max) with the granularity bit set, and lets say the base is 0xFFFF0000.
Using then an effective address (EAX) as say 0xFFFFF, so [DS:EAX] will wrap around and our linear calculation will be virtual address (paging is enabled) 0xEFFFF.
My question is: I have not seen explicitly in words from the processor manual that for 16 bit code segments, it would also wrap around but instead wrap around at 64kb? Or is it possible for 16 bit code segment we can store and load data if say the DS base were to contain a value above 64kb? Or must all memory access be below 64kb mark to prevent truncation?
Thanks!
Using compatibility modes in my long mode OS
Re: Using compatibility modes in my long mode OS
No, 16-bit code segments use exactly the same semantic as 32-bit segments. The only difference is that the limit cannot be larger than 64k. Also, since protected mode has precise limit checking (regardless of segment bitness), if you try to exceed the limit you will get a protection fault.doxrobot wrote: My question is: I have not seen explicitly in words from the processor manual that for 16 bit code segments, it would also wrap around but instead wrap around at 64kb? Or is it possible for 16 bit code segment we can store and load data if say the DS base were to contain a value above 64kb? Or must all memory access be below 64kb mark to prevent truncation?
Re: Using compatibility modes in my long mode OS
Sorry for the confusion I probably could have worded my question better instead of a jumbled paragraph with 10 different question marks in it. You are saying 'No' to it does not wrap around but a 64kb limit is enforced? Or 'No' to it does wrap, and the descriptor must contain a 64kb limit anyway?
sorry
sorry
Re: Using compatibility modes in my long mode OS
The descriptor caches will be setup with a base and limit as usual. All accesses using the descriptor will check so they are within the limits (offsets must be lower than 64kb). If the code executes over the segment limit, and the last instruction happens to end exactly at the 64kb limit, I think execution would resume at address 0 (but I'm not sure, and it is a hypothetical and useless case). However, any accesses using the selector cannot use offsets above 64kb, and will protection fault if this is attempted (using 32-bit addressing, as 16-bit addressing cannot exceed the limit). There will be no wrap-around when adding the base of the segment to the offset, unless 4G is exceeded (just as in the 32-bit case).doxrobot wrote:Sorry for the confusion I probably could have worded my question better instead of a jumbled paragraph with 10 different question marks in it. You are saying 'No' to it does not wrap around but a 64kb limit is enforced? Or 'No' to it does wrap, and the descriptor must contain a 64kb limit anyway?
sorry
Edit: Perhaps the question was if 16-bit addressing modes could result in above 64k offsets? The answer to this is no, they will wrap around (as 16-bit code expects).
Code: Select all
mov eax,10000h
AllocateSmallGlobalMem ; returns 16-bit selector with 64kb limit in es
mov bx,0F000h
mov si,1000h
mov ax,es:[bx+si]
This code would protection fault though:
Code: Select all
mov eax,10000h
AllocateSmallGlobalMem ; returns 16-bit selector with 64kb limit in es
mov ebx,0F000h
mov esi,1000h
mov ax,es:[ebx+esi]
Re: Using compatibility modes in my long mode OS
i mean in your first example. Where you alloc a selector. In legacy x86 since the descriptor base can be any value < 4gb, what if the base loaded into the ES cache is above 64kb. Like 0xFFFFF000. I know with a 16 bit code segment the address/operand size for a general purpose register can't exceed FFFF.
but then assuming ES base is then 0xFFFFF000 and we have this in a 16 bit code segment:
mov si, 0x20
mov bx, [es:si]
that bx will contain the contents of 0xFFFFF020 even though the final linear address computation exceeds 64kb.
it's possible that I have this confused with real mode a20 wrap around as well.
thanks for your help so far rdos
but then assuming ES base is then 0xFFFFF000 and we have this in a 16 bit code segment:
mov si, 0x20
mov bx, [es:si]
that bx will contain the contents of 0xFFFFF020 even though the final linear address computation exceeds 64kb.
it's possible that I have this confused with real mode a20 wrap around as well.
thanks for your help so far rdos
Re: Using compatibility modes in my long mode OS
It can. The 32-bit addressing mode can be used from 16-bit code segments. The assembler will simply add an address size override.doxrobot wrote:i mean in your first example. Where you alloc a selector. In legacy x86 since the descriptor base can be any value < 4gb, what if the base loaded into the ES cache is above 64kb. Like 0xFFFFF000. I know with a 16 bit code segment the address/operand size for a general purpose register can't exceed FFFF.
In fact, most of the code segments in RDOS are 16-bit, and they can use flat selectors and large 32-bit selectors just fine. The only thing the code selector determines is the default address and operand size.
Absolutely. The code selectors in RDOS all have linear base addresses starting from 0xFF000000.doxrobot wrote:but then assuming ES base is then 0xFFFFF000 and we have this in a 16 bit code segment:
mov si, 0x20
mov bx, [es:si]
that bx will contain the contents of 0xFFFFF020 even though the final linear address computation exceeds 64kb.
Real mode is different. The descriptor base is loaded with the segment register value shifted left 4 positions. The A20 gate was added because the first Intel processor(s) would wrap around at 1M, while later processors would not. In fact, the HMA-area (above 1M) was used in the DOS age to gain almost 64k extra memory.doxrobot wrote: it's possible that I have this confused with real mode a20 wrap around as well.
thanks for your help so far rdos