Hello everybody. I'm having problems trying to start up a new Pentium-based CPU. It has 8 MB of RAM (lowest addresses) and 8 MB of FLASH memory (highest addresses). I can load programs with a PC via JTAG into the FLASH (4 chips of 1Mx16, arranged as 1 Mibi of 64-bit words), and I can control the CPU with a Microtek JTAG-ICE (with no trace memory). I can start the programs, step by step or with a 'go forever' command, and all my real-mode programs work as expected. But when I try to load the GDT before switching to protected mode, the program seems to jump to a random address, where it sometimes stops (perhaps after executing a break instruction) and sometimes not (in which cause I can stop the ICE, and CS:EIP is pointing to a random address, anyway) I tried to stop the program with a HLT instruction after the LGDT instruction, to no avail. This is the reset vector, as disassembled by the ICE: dasm cs:fff0 cs:fff1 // CS:FFF0 FA CLI // CS:FFF1 E90CF8 JMP F800 This is the code from the first jump target. Remeber, I can execute the code just up to (and excluding) CS:F810. dasm cs:f800 // CS:F800 FA CLI // CS:F801 B001 MOV AL,01 // CS:F803 B200 MOV DL,00 // CS:F805 B602 MOV DH,02 // CS:F807 EE OUT DX,AL // CS:F808 67668D1D4BF8 LEA EBX,[FFFFF84B] // CS:F80E FFFF // CS:F810 67660F011588 LGDT [FFFFF888] // CS:F816 F8FFFF // CS:F819 F4 HLT // CS:F81A 90 NOP // CS:F81B 90 NOP This the GDT length + linear address: dump fffff888p // FFFFF888P 17 00 90 F8 FF FF i.e., length = 0x17 +1 = 24 (3 entries), address = 0xFFFFF890 This is the GDT: dump fffff890p fffff8a7p word // FFFFF890P 0000 0000 0000 0000 FFFF 0000 9A00 00CF // FFFFF8A0P FFFF 0000 9200 00CF i.e.: selector 0 (0x00): null descriptor selector 1 (0x08): code, 32 GB, read-only selector 2 (0x10): data, 32 GB, read-write These are the CPU registers before execution the LGDT instruction: // EIP = 0x0000F810 // ESP = 0x00000000 // EBP = 0x00000000 // EAX = 0x00000001 // EBX = 0xFFFFF84B // ECX = 0x00000000 // EDX = 0x00000200 // ESI = 0x00000000 // EDI = 0x00000000 // EFLAGS = 0x00000002 // = ivfavrn0oditszapc // CS = 0xF000 // DS = 0x0000 // ES = 0x0000 // FS = 0x0000 // GS = 0x0000 // SS = 0x0000 // GDTBASE = 0x00000000 // GDTLIMIT = 0xFFFF // IDTBASE = 0x00000000 // IDTLIMIT = 0xFFFF // LDTR = 0x0000 // TR = 0x0000 // CR0 = 0x60000010 // CR2 = 0x00000000 // CR3 = 0x00000000 // CR4 = 0x00000008 // LDTBASE = 0x00000000 // LDTLIMIT = 0xFFFF // CSBASE = 0xFFFF0000 // DSBASE = 0x00000000 // ESBASE = 0x00000000 // FSBASE = 0x00000000 // GSBASE = 0x00000000 // SSBASE = 0x00000000 // CSLIMIT = 0x0000FFFF // DSLIMIT = 0x0000FFFF // ESLIMIT = 0x0000FFFF // FSLIMIT = 0x0000FFFF // GSLIMIT = 0x0000FFFF // SSLIMIT = 0x0000FFFF // CSAR = 0x00009300 // DSAR = 0x00009300 // ESAR = 0x00009300 // FSAR = 0x00009300 // GSAR = 0x00009300 // SSAR = 0x00009300 // GDTAR = 0x00008200 // IDTAR = 0x00008200 // LDTAR = 0x00008200 // TSSBASE = 0x00000000 // TSSLIMIT = 0x0000FFFF // TSSAR = 0x00008200 And these are the CPU register after the LGDT instruction + unknown instructions: register // EIP = 0x00007D07 // ESP = 0x0000FFF3 // EBP = 0x00000000 // EAX = 0x00000001 // EBX = 0xFFFFA04B // ECX = 0x00005FBE // EDX = 0x000001FF // ESI = 0x00000000 // EDI = 0x00000000 // EFLAGS = 0x00000016 // = ivfavrn0oditszAPc // CS = 0x46BB // DS = 0x0000 // ES = 0x0000 // FS = 0x0000 // GS = 0x0000 // SS = 0x0000 // GDTBASE = 0x00000000 // GDTLIMIT = 0xFFFF // IDTBASE = 0x00000000 // IDTLIMIT = 0xFFFF // LDTR = 0x0000 // TR = 0x0000 // CR0 = 0x60000010 // CR2 = 0x00000000 // CR3 = 0x00000000 // CR4 = 0x00000008 // LDTBASE = 0x00000000 // LDTLIMIT = 0xFFFF // CSBASE = 0x00046BB0 // DSBASE = 0x00000000 // ESBASE = 0x00000000 // FSBASE = 0x00000000 // GSBASE = 0x00000000 // SSBASE = 0x00000000 // CSLIMIT = 0x0000FFFF // DSLIMIT = 0x0000FFFF // ESLIMIT = 0x0000FFFF // FSLIMIT = 0x0000FFFF // GSLIMIT = 0x0000FFFF // SSLIMIT = 0x0000FFFF // CSAR = 0x00009300 // DSAR = 0x00009300 // ESAR = 0x00009300 // FSAR = 0x00009300 // GSAR = 0x00009300 // SSAR = 0x00009300 // GDTAR = 0x00008200 // IDTAR = 0x00008200 // LDTAR = 0x00008200 // TSSBASE = 0x00000000 // TSSLIMIT = 0x0000FFFF // TSSAR = 0x00008200 Can anybody please throw some light ? -- Ignacio G.T.
Trying to load GDT into a psycho-Pentium
Started by ●September 30, 2004
Reply by ●September 30, 20042004-09-30
bear in mind the processor WILL do segmentation faults while in real mode, I don't remember whether it is a catch-all or if there are more restrictive rules though. So if you really can't figure things like this out you might hook int 0x0d and see if it gets triggered. It has been a while since I did raw protected mode, but the one thing that jumps out at me is you are reading from 0fffff890h with no segment prefix, and with DS=0 where the limit on DS is 0ffffh according to your dumps. This is I think what you do get when you boot... I am wondering if you may get a segmentation fault under these conditions? I don't know for sure on this since I haven't dealt with the boot-up process personally. But if this is the case you can get around it by forcing a CS: prefix on the faulting instruction and changing the offset accordingly. David "Ignacio G.T." wrote:> Hello everybody. > > I'm having problems trying to start up a new Pentium-based CPU. It has 8 MB of > RAM (lowest addresses) and 8 MB of FLASH memory (highest addresses). > > I can load programs with a PC via JTAG into the FLASH (4 chips of 1Mx16, > arranged as 1 Mibi of 64-bit words), and I can control the CPU with a Microtek > JTAG-ICE (with no trace memory). > > I can start the programs, step by step or with a 'go forever' command, and all > my real-mode programs work as expected. But when I try to load the GDT before > switching to protected mode, the program seems to jump to a random address, > where it sometimes stops (perhaps after executing a break instruction) and > sometimes not (in which cause I can stop the ICE, and CS:EIP is pointing to a > random address, anyway) > > I tried to stop the program with a HLT instruction after the LGDT instruction, > to no avail. > > This is the reset vector, as disassembled by the ICE: > > dasm cs:fff0 cs:fff1 > // CS:FFF0 FA CLI > // CS:FFF1 E90CF8 JMP F800 > > This is the code from the first jump target. Remeber, I can execute the code > just up to (and excluding) CS:F810. > > dasm cs:f800 > // CS:F800 FA CLI > // CS:F801 B001 MOV AL,01 > // CS:F803 B200 MOV DL,00 > // CS:F805 B602 MOV DH,02 > // CS:F807 EE OUT DX,AL > // CS:F808 67668D1D4BF8 LEA EBX,[FFFFF84B] > // CS:F80E FFFF > // CS:F810 67660F011588 LGDT [FFFFF888] > // CS:F816 F8FFFF > // CS:F819 F4 HLT > // CS:F81A 90 NOP > // CS:F81B 90 NOP > > This the GDT length + linear address: > > dump fffff888p > // FFFFF888P 17 00 90 F8 FF FF > > i.e., length = 0x17 +1 = 24 (3 entries), address = 0xFFFFF890 > > This is the GDT: > > dump fffff890p fffff8a7p word > // FFFFF890P 0000 0000 0000 0000 FFFF 0000 9A00 00CF > // FFFFF8A0P FFFF 0000 9200 00CF > > i.e.: > selector 0 (0x00): null descriptor > selector 1 (0x08): code, 32 GB, read-only > selector 2 (0x10): data, 32 GB, read-write > > These are the CPU registers before execution the LGDT instruction: > > // EIP = 0x0000F810 > // ESP = 0x00000000 > // EBP = 0x00000000 > // EAX = 0x00000001 > // EBX = 0xFFFFF84B > // ECX = 0x00000000 > // EDX = 0x00000200 > // ESI = 0x00000000 > // EDI = 0x00000000 > // EFLAGS = 0x00000002 > // = ivfavrn0oditszapc > // CS = 0xF000 > // DS = 0x0000 > // ES = 0x0000 > // FS = 0x0000 > // GS = 0x0000 > // SS = 0x0000 > // GDTBASE = 0x00000000 > // GDTLIMIT = 0xFFFF > // IDTBASE = 0x00000000 > // IDTLIMIT = 0xFFFF > // LDTR = 0x0000 > // TR = 0x0000 > // CR0 = 0x60000010 > // CR2 = 0x00000000 > // CR3 = 0x00000000 > // CR4 = 0x00000008 > // LDTBASE = 0x00000000 > // LDTLIMIT = 0xFFFF > // CSBASE = 0xFFFF0000 > // DSBASE = 0x00000000 > // ESBASE = 0x00000000 > // FSBASE = 0x00000000 > // GSBASE = 0x00000000 > // SSBASE = 0x00000000 > // CSLIMIT = 0x0000FFFF > // DSLIMIT = 0x0000FFFF > // ESLIMIT = 0x0000FFFF > // FSLIMIT = 0x0000FFFF > // GSLIMIT = 0x0000FFFF > // SSLIMIT = 0x0000FFFF > // CSAR = 0x00009300 > // DSAR = 0x00009300 > // ESAR = 0x00009300 > // FSAR = 0x00009300 > // GSAR = 0x00009300 > // SSAR = 0x00009300 > // GDTAR = 0x00008200 > // IDTAR = 0x00008200 > // LDTAR = 0x00008200 > // TSSBASE = 0x00000000 > // TSSLIMIT = 0x0000FFFF > // TSSAR = 0x00008200 > > And these are the CPU register after the LGDT instruction + unknown > instructions: > > register > // EIP = 0x00007D07 > // ESP = 0x0000FFF3 > // EBP = 0x00000000 > // EAX = 0x00000001 > // EBX = 0xFFFFA04B > // ECX = 0x00005FBE > // EDX = 0x000001FF > // ESI = 0x00000000 > // EDI = 0x00000000 > // EFLAGS = 0x00000016 > // = ivfavrn0oditszAPc > // CS = 0x46BB > // DS = 0x0000 > // ES = 0x0000 > // FS = 0x0000 > // GS = 0x0000 > // SS = 0x0000 > // GDTBASE = 0x00000000 > // GDTLIMIT = 0xFFFF > // IDTBASE = 0x00000000 > // IDTLIMIT = 0xFFFF > // LDTR = 0x0000 > // TR = 0x0000 > // CR0 = 0x60000010 > // CR2 = 0x00000000 > // CR3 = 0x00000000 > // CR4 = 0x00000008 > // LDTBASE = 0x00000000 > // LDTLIMIT = 0xFFFF > // CSBASE = 0x00046BB0 > // DSBASE = 0x00000000 > // ESBASE = 0x00000000 > // FSBASE = 0x00000000 > // GSBASE = 0x00000000 > // SSBASE = 0x00000000 > // CSLIMIT = 0x0000FFFF > // DSLIMIT = 0x0000FFFF > // ESLIMIT = 0x0000FFFF > // FSLIMIT = 0x0000FFFF > // GSLIMIT = 0x0000FFFF > // SSLIMIT = 0x0000FFFF > // CSAR = 0x00009300 > // DSAR = 0x00009300 > // ESAR = 0x00009300 > // FSAR = 0x00009300 > // GSAR = 0x00009300 > // SSAR = 0x00009300 > // GDTAR = 0x00008200 > // IDTAR = 0x00008200 > // LDTAR = 0x00008200 > // TSSBASE = 0x00000000 > // TSSLIMIT = 0x0000FFFF > // TSSAR = 0x00008200 > > Can anybody please throw some light ? > > -- > Ignacio G.T.
Reply by ●September 30, 20042004-09-30
igtorque.remove@evomer.yahoo.es (Ignacio G.T.) wrote:>// CS:F808 67668D1D4BF8 LEA EBX,[FFFFF84B] >// CS:F80E FFFF >// CS:F810 67660F011588 LGDT [FFFFF888] >// CS:F816 F8FFFF >// CS:F819 F4 HLT32-bit addresses greater than 0xFFFF are illegal in real mode, and cause CPU interrupt 13 (the "pseudo-GPF"). Maybe the CPU jumps to the int 13 vector before HLT is executed. I don't think the LEA instruction causes an exception because the 32-bit address is not de-referenced.>These are the CPU registers before execution the LGDT instruction: >// EIP = 0x0000F810 >// CS = 0xF000 >// CSBASE = 0xFFFF0000>And these are the CPU register after the LGDT instruction + unknown >instructions: > >// EIP = 0x00007D07 >// CS = 0x46BB >// CSBASE = 0x00046BB0_Something_ has caused a far JMP. The INT 13 vector is stored in the 32-bit value at memory location 0x34. Is this value 0x46BB7D07 by chance? P.S. - notice the strange value of CSBASE after reset. If you change the value of the CS register while still in real mode, the CS segment descriptor cache (CSBASE) will be reloaded, and your program will fall down into conventional memory (below 1 megabyte). P.P.S. - I ran your code through Bochs and got this: ======================================================================== Bochs x86 Emulator 2.0 December 21, 2002 ======================================================================== [0x000ffff0] f000:fff0 (unk. ctxt): cli ; fa <bochs:1> setpmem 0x18 4 0x100dead0 (exception 6 -- illegal instruction) <bochs:2> setpmem 0x30 4 0x200dead0 (exception 12 -- stack fault) <bochs:3> setpmem 0x34 4 0x300dead0 (exception 13 -- GPF) <bochs:4> s Next at t=1 (0) [0x000ffff1] f000:fff1 (unk. ctxt): jmp f800 ; e90cf8 <bochs:5> s Next at t=2 (0) [0x000ff800] f000:f800 (unk. ctxt): cli ; fa <bochs:6> s Next at t=3 (0) [0x000ff801] f000:f801 (unk. ctxt): mov AL, 01 ; b001 <bochs:7> s Next at t=4 (0) [0x000ff803] f000:f803 (unk. ctxt): mov DL, 00 ; b200 <bochs:8> s Next at t=5 (0) [0x000ff805] f000:f805 (unk. ctxt): mov DH, 02 ; b602 <bochs:9> s Next at t=6 (0) [0x000ff807] f000:f807 (unk. ctxt): out DX, AL ; ee <bochs:10> s Next at t=7 (0) [0x000ff808] f000:f808 (unk. ctxt): lea EBX, DS:fffff84b ; 66678d1d4bf8ffff <bochs:11> s Next at t=8 (0) [0x000ff810] f000:f810 (unk. ctxt): lgdt DS:fffff888 ; 670f011588f8ffff <bochs:12> s Next at t=9 (0) [0x0003eba2] 300d:ead2 (unk. ctxt): add DS:[BX+SI], AL ; 0000 <bochs:13>
Reply by ●October 1, 20042004-10-01
On Fri, 01 Oct 2004 00:20:59 GMT, David Lindauer <camille@bluegrass.net> wrote:>bear in mind the processor WILL do segmentation faults while in real mode, I don't >remember whether it is a catch-all or if there are more restrictive rules though. >So if you really can't figure things like this out you might hook int 0x0d and see >if it gets triggered.You are right. In fact, after posting the original message, I filled the interrupt vectors zone with pointers to difrent HLT instructions, and the GP vector (0x0d) was triggered.>It has been a while since I did raw protected mode, but the one thing that jumps >out at me is you are >reading from 0fffff890h with no segment prefix, and with DS=0 where the limit on >DS is 0ffffh according to your dumps. This is I think what you do get when you >boot... I am wondering if you may get a segmentation fault under these >conditions? I don't know for sure on this since I haven't dealt with the boot-up >process personally. But if this is the case you can get around it by forcing a >CS: prefix on the faulting instruction and changing the offset accordingly.It sounds reasonable. I'm trying it right now. Thank you, David. -- Ignacio G.T.
Reply by ●October 1, 20042004-10-01
On Fri, 01 Oct 2004 01:31:12 GMT, NoEmailAds@execpc.com (Chris Giese) wrote:>igtorque.remove@evomer.yahoo.es (Ignacio G.T.) wrote: > >>// CS:F808 67668D1D4BF8 LEA EBX,[FFFFF84B] >>// CS:F80E FFFF >>// CS:F810 67660F011588 LGDT [FFFFF888] >>// CS:F816 F8FFFF >>// CS:F819 F4 HLT > >32-bit addresses greater than 0xFFFF are illegal in real mode, >and cause CPU interrupt 13 (the "pseudo-GPF"). Maybe the CPU >jumps to the int 13 vector before HLT is executed. >Mmm. I've read that, although on startup, CS = F000 and EIP = FFF0, the "hidden" part of CS is 0xFFFF0000, so, in fact, you are accessing the highest part of the 4GB linear address space on startup, although only through CS, not through DS, ES, ES or GS.>I don't think the LEA instruction causes an exception because >the 32-bit address is not de-referenced.I agree. In fact, EBX is loaded with FFFFF84B after LEA, and the processor remains controlled by the ICE at this point.> >>These are the CPU registers before execution the LGDT instruction: >>// EIP = 0x0000F810 >>// CS = 0xF000 >>// CSBASE = 0xFFFF0000 > >>And these are the CPU register after the LGDT instruction + unknown >>instructions: >> >>// EIP = 0x00007D07 >>// CS = 0x46BB >>// CSBASE = 0x00046BB0 > >_Something_ has caused a far JMP. The INT 13 vector is stored >in the 32-bit value at memory location 0x34. Is this value >0x46BB7D07 by chance?You are right. I know now that a GP is being caused by the LGDT instruction.> >P.S. - notice the strange value of CSBASE after reset. If you >change the value of the CS register while still in real mode, >the CS segment descriptor cache (CSBASE) will be reloaded, and your >program will fall down into conventional memory (below 1 megabyte). > >P.P.S. - I ran your code through Bochs and got this: > >======================================================================== > Bochs x86 Emulator 2.0 > December 21, 2002 >======================================================================== >[0x000ffff0] f000:fff0 (unk. ctxt): cli ; fa ><bochs:1> setpmem 0x18 4 0x100dead0 (exception 6 -- illegal instruction) ><bochs:2> setpmem 0x30 4 0x200dead0 (exception 12 -- stack fault) ><bochs:3> setpmem 0x34 4 0x300dead0 (exception 13 -- GPF) ><bochs:4> s >Next at t=1 >(0) [0x000ffff1] f000:fff1 (unk. ctxt): jmp f800 ; e90cf8 ><bochs:5> s >Next at t=2 >(0) [0x000ff800] f000:f800 (unk. ctxt): cli ; fa ><bochs:6> s >Next at t=3 >(0) [0x000ff801] f000:f801 (unk. ctxt): mov AL, 01 ; b001 ><bochs:7> s >Next at t=4 >(0) [0x000ff803] f000:f803 (unk. ctxt): mov DL, 00 ; b200 ><bochs:8> s >Next at t=5 >(0) [0x000ff805] f000:f805 (unk. ctxt): mov DH, 02 ; b602 ><bochs:9> s >Next at t=6 >(0) [0x000ff807] f000:f807 (unk. ctxt): out DX, AL ; ee ><bochs:10> s >Next at t=7 >(0) [0x000ff808] f000:f808 (unk. ctxt): lea EBX, DS:fffff84b ; 66678d1d4bf8ffff ><bochs:11> s >Next at t=8 >(0) [0x000ff810] f000:f810 (unk. ctxt): lgdt DS:fffff888 ; 670f011588f8ffff ><bochs:12> s >Next at t=9 >(0) [0x0003eba2] 300d:ead2 (unk. ctxt): add DS:[BX+SI], AL ; 0000 ><bochs:13> >Thank you very much, Chris. -- Ignacio G.T.
Reply by ●October 1, 20042004-10-01
On Fri, 01 Oct 2004 09:30:57 GMT, igtorque.remove@evomer.yahoo.es (Ignacio G.T.) wrote:>On Fri, 01 Oct 2004 00:20:59 GMT, David Lindauer <camille@bluegrass.net> wrote: > >>bear in mind the processor WILL do segmentation faults while in real mode, I don't >>remember whether it is a catch-all or if there are more restrictive rules though. >>So if you really can't figure things like this out you might hook int 0x0d and see >>if it gets triggered. > >You are right. In fact, after posting the original message, I filled the >interrupt vectors zone with pointers to difrent HLT instructions, and the GP >vector (0x0d) was triggered. > >>It has been a while since I did raw protected mode, but the one thing that jumps >>out at me is you are >>reading from 0fffff890h with no segment prefix, and with DS=0 where the limit on >>DS is 0ffffh according to your dumps. This is I think what you do get when you >>boot... I am wondering if you may get a segmentation fault under these >>conditions? I don't know for sure on this since I haven't dealt with the boot-up >>process personally. But if this is the case you can get around it by forcing a >>CS: prefix on the faulting instruction and changing the offset accordingly. > >It sounds reasonable. I'm trying it right now. > >Thank you, David. >Bad news, David. I've just tried LGDT CS:[FFFFF888] and the results are the same. Intel's manual says this, for the LGDT instruction: === Real-Address Mode Exceptions ------------------------------------ #UD If source operand is not a memory location. #GP If a memory operand effective address is outside the CS, DS, ES, FS, or GS segment limit. #SS If a memory operand effective address is outside the SS segment limit. === We know its a #GP, but I still don't know why. Perhaps I should try copying the GDT to RAM and trying to load it from there... -- Ignacio G.T.
Reply by ●October 1, 20042004-10-01
>=== > >We know its a #GP, but I still don't know why. Perhaps I should try copying the >GDT to RAM and trying to load it from there... >Well, that has worked. Copy the GTD to RAM (0x0400), copy the GDT descriptor just after the GDT (0x0418), and load the GDT with LGDT 0x00000418. Now, switching to protected mode. Stay tuned... -- Ignacio G.T.
Reply by ●October 1, 20042004-10-01
Ignacio G.T. wrote:> Bad news, David. I've just tried > > LGDT CS:[FFFFF888] > > and the results are the same. > > Intel's manual says this, for the LGDT instruction: >Did you try LGDT CS:[f888] Please note that the processor is in *16* bit mode till the descriptors are in and protected mode is turned on. There is somewhere in the back of my trash box a piece of code that boots an i386 into 32-bit protected mode. If it is of any help, I could find it among the dusty backup CD's. Tauno Voipio tauno voipio (at) iki fi
Reply by ●October 1, 20042004-10-01
Looks like you have had some good advice and thinking already. Rather than try and understand it all, I'll just add some quick thoughts of my own. When the processor starts up, it starts in 'real' mode. It's still actually in protected mode, but the internal cached versions of descriptor entries are pre-loaded by the processor reset to use USE16 segment interpretations and to specify default behavior that 'appears' to be real mode behavior. In your case, you correctly identify the fact that the CPU, by default, starts up at the end of 32-bit memory, using CS = F000 and EIP = 0000FFF0. However, the CS register's contents are essentially ignored during operation, as they are meaningless to the actual hardware. Instead, the hardware uses the "hidden" cached copies of the descriptor, which on reset for the CS are: Value = F000H Base = FFFF0000H Limit = FFFFH AR = Present, R/W, Accessed The value, as I said, isn't used by the bus interface unit. It is always ignored. When you load a segment/selector register, the processor looks at CR0 to determine "real or protected" and then either precodes the base and limit through a fixed calculation on the loaded value (if in real mode) or else goes out into memory and loads them from the indicated place. But in no case, not ever, whether CR0 says real or protected mode, does the processor's BIU ever use the value field. It's ignored, except for a tiny moment in time when it first gets loaded. So when you say the "hidden part of CS is 0xFFFF0000" what you really mean is that the base field of the cached area related to CS is that value. Note that the Limit is still 0xFFFF! This will be used, whether or not you like it, to validate any offset values you try and apply when referring to CS. You need your offset to remain within a 64k area of where the CS base refers. I *do* have to disagree with Chris when he says, "32-bit addresses greater than 0xFFFF are illegal in real mode." It is CR0 that decides what mode your are in, but that has absolutely nothing to do with what kind of offsets are accepted. It is strictly the Limit field of the cached region in the CPU associated with the selector that decides this. And it does so without any regard whatsoever for the CR0 status. You can load up the CS when in protected mode and thereby control what goes into this cache and then you can switch back to real mode and the cached Limit field will still operate. If you set it to some very large limit, you will be allowed to use very large offsets even while in what is supposed to be real mode, according to the CR0 condition. So long as you don't reload CS while in real mode you won't blow that cached value. Of course, if you do change CS while in real mode, that Limit field will immediately get recoded back to 0xFFFF and your CS segment will again be limited. One thing to keep in mind is that when the processor first comes out of reset it does NOT have paging enabled. Without paging, it is impossible to generate anything other than 0 for the upper 4 bits of the 36 bit physical addresses. Instead, only the low-order 32-bits are used. The initial address executed has to be found in the flash or ROM that must be located at that place. The first JMP you encounter, the one going to 0xF800, does not change the CS. So these addresses are still "high." Your LGDT is executed quite quickly, I gather, after that point. I assume that your CR0 still has you in real mode at this point in time and that the Limit field for the CS still applies and is tiny. As such, your offset there is far too big. Also, take a close look at the description for the LGDT instruction. I've usually used a DB 66h before the instruction to force the operand size from the USE16 I'm currently running in to the USE32 interpretation, because I want the 16-bit limit and 32-bit base, not the 16-bit limit and 24-bit base for the data I'm pointing to. Also, you'll need to then change CR0 and perform a JMP to flush the instruction pipeline to start new instruction interpretations afterwards. Does any of that help? Jon
Reply by ●October 2, 20042004-10-02
that won't work because you have to take into account the base address of CS:... which is FFFF0000. you should do: LGDT CS:[F888] what you did GPFs because the limit on CS is 64K as well, and when you add in the base you are out of range. David "Ignacio G.T." wrote:> On Fri, 01 Oct 2004 09:30:57 GMT, igtorque.remove@evomer.yahoo.es (Ignacio G.T.) > wrote: > > >On Fri, 01 Oct 2004 00:20:59 GMT, David Lindauer <camille@bluegrass.net> wrote: > > > >>bear in mind the processor WILL do segmentation faults while in real mode, I don't > >>remember whether it is a catch-all or if there are more restrictive rules though. > >>So if you really can't figure things like this out you might hook int 0x0d and see > >>if it gets triggered. > > > >You are right. In fact, after posting the original message, I filled the > >interrupt vectors zone with pointers to difrent HLT instructions, and the GP > >vector (0x0d) was triggered. > > > >>It has been a while since I did raw protected mode, but the one thing that jumps > >>out at me is you are > >>reading from 0fffff890h with no segment prefix, and with DS=0 where the limit on > >>DS is 0ffffh according to your dumps. This is I think what you do get when you > >>boot... I am wondering if you may get a segmentation fault under these > >>conditions? I don't know for sure on this since I haven't dealt with the boot-up > >>process personally. But if this is the case you can get around it by forcing a > >>CS: prefix on the faulting instruction and changing the offset accordingly. > > > >It sounds reasonable. I'm trying it right now. > > > >Thank you, David. > > > > Bad news, David. I've just tried > > LGDT CS:[FFFFF888] > > and the results are the same. > > Intel's manual says this, for the LGDT instruction: > > === > Real-Address Mode Exceptions > ------------------------------------ > #UD If source operand is not a memory location. > #GP If a memory operand effective address is outside the CS, DS, ES, FS, or > GS segment limit. > #SS If a memory operand effective address is outside the SS segment limit. > === > > We know its a #GP, but I still don't know why. Perhaps I should try copying the > GDT to RAM and trying to load it from there... > > -- > Ignacio G.T.