Page 1 of 3
[solved] Real Mode Confusion
Posted: Tue Oct 25, 2011 4:34 pm
by RobertF
I've followed the instructions at the Real Mode wiki page and the appropriate section for the IA-32 Developer's Manual for switching back to real mode from protected mode. However, it's been giving me troubles, and I'm sure I'm missing something:
- - The system will only switch back to real mode if the program's start address is under 0x8000. I thought I was not working with a 1:1 page, but after identity paging the first 0x100000 bytes, I still get the same result.
- Bochs will throw different errors depending on what the start address and what sp is set to after switching to real mode: the closest I've gotten was the start address at 0x6000 and sp at 0x9000. However, any interrupt made to 0x10 after interrupts are restored will switch the VGA mode to 13h under Bochs, and has no result under VirtualBox. I assume this is because it's executing random code.
The Real Mode wiki page notes that sp should be set so that the program doesn't interfere with it—this confuses me. Also I was under the assumption that I could load the real mode program anywhere under 1MB; is it possible that loading it at 0x6000 is interfering with another part of the system? How could I check for this?
Re: Real Mode Confusion
Posted: Tue Oct 25, 2011 6:40 pm
by theseankelly
Not an expert on the topic, but here's a stab at it:
In real mode, you have access to 32bit memory, but only have a 16 bit IP register. So if you try going to real mode with IP set to a 32bit address, it's going to go to the instruction at the address in the lower 16 bits -- explains why you see random instructions being executed.
[edit] just re-read your post and see that the above probably doesn't apply to what you're doing [/edit]
Also, double check the memory map for low memory as there are some restrictions as to where you can load things. Make sure what you're loading fits and doesn't start overriding EBDA and video, etc
http://wiki.osdev.org/Memory_Map_%28x86%29
Re: Real Mode Confusion
Posted: Tue Oct 25, 2011 8:06 pm
by RobertF
theseankelly wrote:Not an expert on the topic, but here's a stab at it:
In real mode, you have access to 32bit memory, but only have a 16 bit IP register. So if you try going to real mode with IP set to a 32bit address, it's going to go to the instruction at the address in the lower 16 bits -- explains why you see random instructions being executed.
[edit] just re-read your post and see that the above probably doesn't apply to what you're doing [/edit]
Also, double check the memory map for low memory as there are some restrictions as to where you can load things. Make sure what you're loading fits and doesn't start overriding EBDA and video, etc
http://wiki.osdev.org/Memory_Map_%28x86%29
I'm probably wrong in saying the program is executing random instructions—bochs switches to mode 13h regardless of what mode I specify. If I don't interrupt 0x10, nothing happens.
However, loading at 0x6000 has been the only location which was semi-sucessful (where bochs switched graphics modes, even though I was switching to 40x25 text mode). 0x6000 shouldn't overwrite any memory, but I moved the program down to 0x7E00 just in case. I feel the sp is part of the problem here, and when set to 0x500, the system goes to real mode but doesn't seem to handle interrupts or changing the real mode segment selector. When set to a value like 0x8000, bochs will throw errors—how should I appropriately set sp?
Re: Real Mode Confusion
Posted: Tue Oct 25, 2011 8:57 pm
by AndrewBuckley
how big is your program? you only have 0x00000 to 0x9FFFF(640KB)
if you go into 0xa0000 and up you may run into problems.
Re: Real Mode Confusion
Posted: Tue Oct 25, 2011 9:11 pm
by Chandra
RobertF wrote:- The system will only switch back to real mode if the program's start address is under 0x8000. I thought I was not working with a 1:1 page, but after identity paging the first 0x100000 bytes, I still get the same result.
- Bochs will throw different errors depending on what the start address and what sp is set to after switching to real mode: the closest I've gotten was the start address at 0x6000 and sp at 0x9000. However, any interrupt made to 0x10 after interrupts are restored will switch the VGA mode to 13h under Bochs, and has no result under VirtualBox. I assume this is because it's executing random code.
Returning back to Real Mode involves restoring the complete real mode environment. This includes remapping the PIC to the default real mode vectors, reloading the GDT with 64 kb segment limit and reverting any other hardware changes you made(
for example, you may need to restore the Floppy controller to default PIO mode). You didn't mention what you've done so far, so it's hard to tell what's happening with the code.
RobertF wrote:The Real Mode wiki page notes that sp should be set so that the program doesn't interfere with it—this confuses me.
That's because randomly setting up SP may corrupt the Stack. If your code overwrites the stack, that's the worst you can get to.
Re: Real Mode Confusion
Posted: Wed Oct 26, 2011 7:24 am
by turdus
That's absolutely normal behavior in real mode. You have 64k segments, addressed by segment registers. I'm quite sure you didn't set ss, so it's 0, thus creates a memory window at 0-65535. Because offsets are signed values, you can use -32767..+32768 (that is 8000h in hex).
No wonder your code acts strange if you put your stack outside of the window, the pointer will be truncated and you address a different part of memory.
Solutions:
1. put your stack in the window, like before your code at 800h or 600h. It's quite common, although provides a small stack only (which should be more than enough by the way) because 4FFh is BIOS area that should not be messed up. Most boot loaders do this (stack at 800h, growing downwards, code at 800h, growing upwards).
2. set up cs (for your code), ds (for your data) and ss (for the stack), and you'll have 3 different (maybe overlapping) 64k windows.
And read this:
http://wiki.osdev.org/Segmentation
Re: Real Mode Confusion
Posted: Wed Oct 26, 2011 11:00 pm
by RobertF
turdus wrote:That's absolutely normal behavior in real mode. You have 64k segments, addressed by segment registers. I'm quite sure you didn't set ss, so it's 0, thus creates a memory window at 0-65535. Because offsets are signed values, you can use -32767..+32768 (that is 8000h in hex).
No wonder your code acts strange if you put your stack outside of the window, the pointer will be truncated and you address a different part of memory.
Solutions:
1. put your stack in the window, like before your code at 800h or 600h. It's quite common, although provides a small stack only (which should be more than enough by the way) because 4FFh is BIOS area that should not be messed up. Most boot loaders do this (stack at 800h, growing downwards, code at 800h, growing upwards).
2. set up cs (for your code), ds (for your data) and ss (for the stack), and you'll have 3 different (maybe overlapping) 64k windows.
And read this:
http://wiki.osdev.org/Segmentation
No good; putting the stack inside the window still gives me errors (and sometimes I get an invalid opcode interrupt, depending on whether I test it in VirtualBox or Bochs). I've also tried setting up ds and ss (since I read that you can't modify cs, and when I do, bochs complains) for different 64K windows, but that didn't solve the problem either.
I've also remapped the PIC to its original offsets like Chandra suggested but that didn't work, either.
Re: Real Mode Confusion
Posted: Thu Oct 27, 2011 3:12 am
by Chandra
RobertF wrote:No good; putting the stack inside the window still gives me errors (and sometimes I get an invalid opcode interrupt, depending on whether I test it in VirtualBox or Bochs). I've also tried setting up ds and ss (since I read that you can't modify cs, and when I do, bochs complains) for different 64K windows, but that didn't solve the problem either.
I've also remapped the PIC to its original offsets like Chandra suggested but that didn't work, either.
Can you post the related code? We may find something there.
Re: Real Mode Confusion
Posted: Thu Oct 27, 2011 5:27 am
by turdus
Agree with Chandra, show your code. I'm pretty sure you have a bug somewhere that ruins the stack.
In the meanwhile, some reading:
http://forum.osdev.org/viewtopic.php?f=1&t=23125
it's a working code example that switches from long to real and back to long again. I know you need prot to real, but you can spot what has to be done (setting idt, turning paging off, remapping pic, loading segment registers etc.)
Re: Real Mode Confusion
Posted: Thu Oct 27, 2011 7:05 am
by RobertF
Code: Select all
[bits 32]
[org 0x7E00]
PMode32:
cli ; disable interrupts
mov eax, cr0
and eax, 0x7FFFFFFF ; clear pg bit
mov cr0, eax
xor eax, eax
mov cr3, eax ; flush TLB
jmp 0x18:PMode16 ; far jump to 16-bit protected mode
[bits 16]
RealIDT:
dw 0x3FF
dd 0
PMode16:
mov ax, 0x20 ; load 16-bit gdt data segment
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax
mov ss, ax
lidt [RealIDT]
mov eax, cr0
and eax, 0xFFFFFFFE ; clear pe bit
mov cr0, eax
jmp 0:RMode ; far jump to real mode
RMode:
mov sp, 0x600
mov ax, 0
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax
mov ss, ax
sti
mov ah,0x0
mov al,0x2 ; 40x25 text mode
int 0x10
ret
Re: Real Mode Confusion
Posted: Thu Oct 27, 2011 9:43 am
by Chandra
That return will take you to a trip of roller-coaster.
RobertF wrote:mov sp, 0x600
Plain Trouble. The most likely cause of the code failure.
Hint: Reserve some static space for the stack.Code: Select all
lidt [RealIDT]
mov eax, cr0
and eax, 0xFFFFFFFE ; clear pe bit
mov cr0, eax
I would load the
Real Mode IVT after entering Real Mode.
Re: Real Mode Confusion
Posted: Thu Oct 27, 2011 12:02 pm
by RobertF
Chandra wrote:
RobertF wrote:mov sp, 0x600
Plain Trouble. The most likely cause of the code failure.
Hint: Reserve some static space for the stack.
Hmm, I tried that and now Bochs (and Virtual Box) doesn't seemingly do anything/report any errors, although it's still switching to real mode.
What I changed (along with your other suggestions):
Code: Select all
RMode:
mov sp, stack
mov ax, 0
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax
mov ss, ax
sti ; now in real mode with proper segments—done
mov ah,0x0
mov al,13h ; 40x25 text mode
int 0x10
[section .bss]
stack:
resb 0x600
I feel like I'm missing something very very simple here.
Re: Real Mode Confusion
Posted: Thu Oct 27, 2011 12:44 pm
by theseankelly
RobertF wrote:
What I changed (along with your other suggestions):
Code: Select all
RMode:
mov sp, stack
mov ax, 0
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax
mov ss, ax
sti ; now in real mode with proper segments—done
mov ah,0x0
mov al,13h ; 40x25 text mode
int 0x10
[section .bss]
stack:
resb 0x600
I feel like I'm missing something very very simple here.
I think that since the stack grows downward, what you want is this:
Also, do you really need a 1.5kb stack?
Re: Real Mode Confusion
Posted: Thu Oct 27, 2011 12:59 pm
by theseankelly
Also I'm a little confused as to why everyone thinks the stack is the problem. I agree it will be eventually, but the code shown that's failing doesn't actually use the stack yet right?
Re: Real Mode Confusion
Posted: Thu Oct 27, 2011 1:53 pm
by gerryg400
theseankelly wrote:Also I'm a little confused as to why everyone thinks the stack is the problem. I agree it will be eventually, but the code shown that's failing doesn't actually use the stack yet right?
and
both use the stack