[solved] Real Mode Confusion

Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
RobertF
Member
Member
Posts: 25
Joined: Tue Oct 18, 2011 12:55 am

[solved] Real Mode Confusion

Post 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?
Last edited by RobertF on Tue Nov 01, 2011 5:05 pm, edited 1 time in total.
theseankelly
Posts: 20
Joined: Sat Oct 22, 2011 4:17 pm

Re: Real Mode Confusion

Post 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
RobertF
Member
Member
Posts: 25
Joined: Tue Oct 18, 2011 12:55 am

Re: Real Mode Confusion

Post 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?
AndrewBuckley
Member
Member
Posts: 95
Joined: Thu Jan 29, 2009 9:13 am

Re: Real Mode Confusion

Post 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.
User avatar
Chandra
Member
Member
Posts: 487
Joined: Sat Jul 17, 2010 12:45 am

Re: Real Mode Confusion

Post 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.
Programming is not about using a language to solve a problem, it's about using logic to find a solution !
User avatar
turdus
Member
Member
Posts: 496
Joined: Tue Feb 08, 2011 1:58 pm

Re: Real Mode Confusion

Post 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
RobertF
Member
Member
Posts: 25
Joined: Tue Oct 18, 2011 12:55 am

Re: Real Mode Confusion

Post 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.
User avatar
Chandra
Member
Member
Posts: 487
Joined: Sat Jul 17, 2010 12:45 am

Re: Real Mode Confusion

Post 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.
Programming is not about using a language to solve a problem, it's about using logic to find a solution !
User avatar
turdus
Member
Member
Posts: 496
Joined: Tue Feb 08, 2011 1:58 pm

Re: Real Mode Confusion

Post 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.)
RobertF
Member
Member
Posts: 25
Joined: Tue Oct 18, 2011 12:55 am

Re: Real Mode Confusion

Post 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
User avatar
Chandra
Member
Member
Posts: 487
Joined: Sat Jul 17, 2010 12:45 am

Re: Real Mode Confusion

Post by Chandra »

Code: Select all

ret
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.
Programming is not about using a language to solve a problem, it's about using logic to find a solution !
RobertF
Member
Member
Posts: 25
Joined: Tue Oct 18, 2011 12:55 am

Re: Real Mode Confusion

Post 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.
theseankelly
Posts: 20
Joined: Sat Oct 22, 2011 4:17 pm

Re: Real Mode Confusion

Post 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:

Code: Select all

[section .bss]
             resb 0x600   
stack:
Also, do you really need a 1.5kb stack?
theseankelly
Posts: 20
Joined: Sat Oct 22, 2011 4:17 pm

Re: Real Mode Confusion

Post 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?
gerryg400
Member
Member
Posts: 1801
Joined: Thu Mar 25, 2010 11:26 pm
Location: Melbourne, Australia

Re: Real Mode Confusion

Post 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?

Code: Select all

int 0x10
and

Code: Select all

ret
both use the stack
If a trainstation is where trains stop, what is a workstation ?
Post Reply