I can't switch back to real mode properly (Gave up)

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.
mikegonta
Member
Member
Posts: 229
Joined: Thu May 19, 2011 5:13 am
Contact:

Re: I can't switch back to real mode properly

Post by mikegonta »

Brendan wrote:However not using virtual8086 also adds complexity (e.g. trying to figure out how to prevent things from locking up because various
IRQs occurred when you happened to be in real mode and the device drivers responsible for those devices don't get the IRQs).
Nobody said it was easy.
However, it's not that complicated. Simply hook the real mode interrupts which transition to their equivalent PM32 interrupt. The default
PM32 handlers transition back to RM16 and execute the original IVT handlers. This way all interrupts are handled in PM32 (including those
which occur while in RM16).
Mike Gonta
look and see - many look but few see

https://mikegonta.com
User avatar
Ycep
Member
Member
Posts: 401
Joined: Mon Dec 28, 2015 11:11 am

Re: I can't switch back to real mode properly

Post by Ycep »

Code: Select all

__asm cli
PicInit(0x08,0x0F);
PicInit(0x70,0x77);
SetDscp(1,0,0xffff,GDT_DESC_READWRITE|GDT_DESC_EXEC|GDT_DESC_CODEDATA|GDT_DESC_MEMORY, GDT_GRAND_4K |GDT_GRAND_LIMITHI_LAYER);
SetDscp(2,0,0xffff,GDT_DESC_READWRITE|GDT_DESC_CODEDATA|GDT_DESC_MEMORY,GDT_GRAND_4K | GDT_GRAND_LIMITHI_LAYER);
SetDscp(3,0,0xffff,GDT_DESC_READWRITE|GDT_DESC_EXEC|GDT_DESC_CODEDATA|GDT_DESC_MEMORY|GDT_DESC_DPL,GDT_GRAND_4K|GDT_GRAND_LIMITHI_LAYER);
SetDscp(4,0,0xffff,GDT_DESC_READWRITE|GDT_DESC_CODEDATA|GDT_DESC_MEMORY|GDT_DESC_DPL,GDT_GRAND_4K | GDT_GRAND_LIMITHI_LAYER);
__asm
{
	mov ax, 0
	;jmp cs:ax Illegal segment override in first operand and illegal instruction size
	mov eax, cr0
	and eax, 0xFFFFFFFE
	mov cr0, eax
	mov ax, 0
	mov ds, ax
	mov fs, ax
	mov es, ax
	mov gs, ax
	mov ss, ax
	sti
}
How can i load IVT?, i don't understand.
I know this is all wrong.
User avatar
BrightLight
Member
Member
Posts: 901
Joined: Sat Dec 27, 2014 9:11 am
Location: Maadi, Cairo, Egypt
Contact:

Re: I can't switch back to real mode properly

Post by BrightLight »

Put this code in it's own assembly file, not from C.
Do something like this:

Code: Select all

use32
	; in your C code, remap the master PIC to INT 8 and slave PIC to INT 0x70 after disabling interrupts with CLI
	; then execute this code which should be in its own assembly file, everything 16-bit should be done here and NOT in C/C++
	; assuming 0x18 is a 16-bit protected mode code descriptor, and 0x20 is a 16-bit protected mode data descriptor
	cli

	; you must be in an identity-mapped area if you use paging
	mov eax, cr0
	and eax, 0x7FFFFFFF		; disable paging
	mov cr0, eax

	jmp 0x18:.pmode16

use16

.pmode16:
	mov ax, 0x20
	mov ss, ax
	mov ds, ax
	mov es, ax
	mov fs, ax
	mov gs, ax

	mov eax, cr0
	and eax, 0xFFFFFFFE		; disable protection
	mov cr0, eax1
	jmp REAL_MODE_SEGMENT:.real_mode

.real_mode:
	mov ax, REAL_MODE_SEGMENT
	mov ss, ax
	mov ds, ax
	mov es, ax
	mov fs, ax
	mov gs, ax
	mov sp, REAL_MODE_STACK

	lidt [.bios_ivt]
	sti

	; continue in real mode ;)

.bios_ivt:		; this really is an IDTR for the BIOS
	.limit		dw 0x3FF
	.base		dd 0
You know your OS is advanced when you stop using the Intel programming guide as a reference.
User avatar
Ycep
Member
Member
Posts: 401
Joined: Mon Dec 28, 2015 11:11 am

Re: I can't switch back to real mode properly

Post by Ycep »

I didn't wanted any copy-paste source.
I know i need to use assembly file, Mike said that already.
At same time, i don't use paging; that's why i ignore it everywhere.
User avatar
BrightLight
Member
Member
Posts: 901
Joined: Sat Dec 27, 2014 9:11 am
Location: Maadi, Cairo, Egypt
Contact:

Re: I can't switch back to real mode properly

Post by BrightLight »

Well, at least study my code without copying/pasting it. It gives you an idea of what to do in C, what to do in assembly, and how to load the IVT after entering real mode.
You know your OS is advanced when you stop using the Intel programming guide as a reference.
User avatar
neon
Member
Member
Posts: 1567
Joined: Sun Feb 18, 2007 7:28 pm
Contact:

Re: I can't switch back to real mode properly

Post by neon »

Hello,

Read through the code provided by omarrx024 - it goes through the basic process of what you need to do. Note that code assumes the 16 bit data selector is GDT index 4 and code selector is index 3. You can ignore the paging stuff since its not being used (that will actually make the whole process much simpler.) If it helps, copy and paste it for now as a starting point - to use it properly you'll need to learn how it works anyways.

Is that the same code you use to set up the initial GDT in the kernel? The reason I find it odd, is that you have to specifically set GDT_GRAND_32BIT for index 1, and 2 in order for your code to even run. Index 3 and 4 wouldn't need this. That should be the only difference you need. Don't use GDT_DESC_DPL yet until you are ready for user mode.
OS Development Series | Wiki | os | ncc
char c[2]={"\x90\xC3"};int main(){void(*f)()=(void(__cdecl*)(void))(void*)&c;f();}
User avatar
BrightLight
Member
Member
Posts: 901
Joined: Sat Dec 27, 2014 9:11 am
Location: Maadi, Cairo, Egypt
Contact:

Re: I can't switch back to real mode properly

Post by BrightLight »

Offtopic: it seems you want to use VGA mode 0x12. That can be achieved by using a VGA driver, but that probably isn't for you yet. After implementing real mode, you should use VESA instead; it gives you much higher resolutions and high color quality (up to 24/32 bits per pixel) and is also relatively simple.
And even if you don't need a VGA driver to set the mode, you'll need portions of a VGA driver to switch planes, because mode 0x12 doesn't expose all its memory in one segment because it's too much, and I'm pretty sure you don't want to call the BIOS 4 times to draw one pixel!
So overall, VESA will save you effort, performance and looks.
You know your OS is advanced when you stop using the Intel programming guide as a reference.
User avatar
Ycep
Member
Member
Posts: 401
Joined: Mon Dec 28, 2015 11:11 am

Re: I can't switch back to real mode properly

Post by Ycep »

Thanks omarrx024, neon and others, but
How could i use assembly file with using VS? I can't? I need to use Cygwin i686-elf GCC or Linux? Or not?
User avatar
Ycep
Member
Member
Posts: 401
Joined: Mon Dec 28, 2015 11:11 am

Re: I can't switch back to real mode properly

Post by Ycep »

omarrx024 wrote:Offtopic: it seems you want to use VGA mode 0x12. That can be achieved by using a VGA driver, but that probably isn't for you yet. After implementing real mode, you should use VESA instead; it gives you much higher resolutions and high color quality (up to 24/32 bits per pixel) and is also relatively simple.
And even if you don't need a VGA driver to set the mode, you'll need portions of a VGA driver to switch planes, because mode 0x12 doesn't expose all its memory in one segment because it's too much, and I'm pretty sure you don't want to call the BIOS 4 times to draw one pixel!
So overall, VESA will save you effort, performance and looks.
Yes, but i still need switching to real mode for VESA how i remember...
zdz
Member
Member
Posts: 47
Joined: Tue Feb 10, 2015 3:36 pm

Re: I can't switch back to real mode properly

Post by zdz »

lukaandjelkovic wrote:Thanks omarrx024, neon and others, but
How could i use assembly file with using VS? I can't? I need to use Cygwin i686-elf GCC or Linux? Or not?
You can. You could use an assembler set a special build step. I think there is a wiki page about this. But I can privire an exemple if you can't figure it out.
User avatar
neon
Member
Member
Posts: 1567
Joined: Sun Feb 18, 2007 7:28 pm
Contact:

Re: I can't switch back to real mode properly

Post by neon »

Just use something like nasm, have it output a win32 object file, and tell the linker to import it in. You can either do this separately or have it as a "special build step" within the visual c++ IDE. Also, you have not addressed any of my questions regarding the GDT nor its Wiki page. Why is that?
OS Development Series | Wiki | os | ncc
char c[2]={"\x90\xC3"};int main(){void(*f)()=(void(__cdecl*)(void))(void*)&c;f();}
User avatar
Ycep
Member
Member
Posts: 401
Joined: Mon Dec 28, 2015 11:11 am

Re: I can't switch back to real mode properly

Post by Ycep »

neon wrote:Just use something like nasm, have it output a win32 object file, and tell the linker to import it in. You can either do this separately or have it as a "special build step" within the visual c++ IDE. Also, you have not addressed any of my questions regarding the GDT nor its Wiki page. Why is that?
Not sure what did you mean by that "i didn't addressed" your questions regarding GDT... I do not want anything bad to you...
You mean i didn't mentioned? If so, i mentioned that on PM.
Hmmm... Is there any way to switch to any non-outdated graphical mode without using any interrupts or using real mode which isn't Bochs Graphics Adapter?
I mean, can VESA be loaded without using interrupts or real mode?
I would really likey that if it's possible, because that is only reason why i use switcher to real mode...
[-o< (Say yes... Please...)
P.S. Congratulations Mike, your made Leet (1337) posts!
Octocontrabass
Member
Member
Posts: 5587
Joined: Mon Mar 25, 2013 7:01 pm

Re: I can't switch back to real mode properly

Post by Octocontrabass »

lukaandjelkovic wrote:I mean, can VESA be loaded without using interrupts or real mode?
You could write (or port) an x86 emulator and use it to run the real-mode video BIOS code. This is more work than switching to real mode, but it means you don't have to switch to real mode. (It can also be useful for figuring out how to write a native driver for the video card.)

It should go without saying that the emulated CPU needs to be given access to the real video card for this to work.
User avatar
~
Member
Member
Posts: 1228
Joined: Tue Mar 06, 2007 11:17 am
Libera.chat IRC: ArcheFire

Re: I can't switch back to real mode properly

Post by ~ »

You can learn to switch video modes from Protected Mode itself with this tutorial:

Implementing a Function to Switch Standard VGA Video Modes
Implementing a Function to Switch Standard VGA Video Modes
Implementing a Function to Switch Standard VGA Video Modes
Implementing a Function to Switch Standard VGA Video Modes
lukaandjelkovic wrote:Hi, i was trying to call interrupts to get in graphics mode. I done that before by doing this in bootloader:

Code: Select all

mov ah, 0
mov al, 0x12
int 0x10
Now i want to do it in kernel.
Remember my last post : http://forum.osdev.org/viewtopic.php?f=1&t=30380? OK, there i tried to call interrupts.
To get into real mode i do this:

Code: Select all

cli
mov eax, cr0
and eax, 0
mov cr0, eax
sti
In __asm block. I just change first bit in CR0.
To get back to protected mode, i do this:

Code: Select all

cli
mov eax, cr0
xor eax, 1
mov cr0, eax
		
mov ax, 0
mov ds, ax
mov fs, ax
mov es, ax
mov gs, ax
mov ss, ax
mov esp, 2097000
I remove that first bit from CR0, reset segment registers and set stack 2097000 (It's always at that location. My OS requires minimum 2MB of RAM.)

It seem to halt at int 0x10. That means somehow, it's still in protected mode.
Hmmm, i do not get to real mode right.
Any ideas to fix this?
Yeah, also removed deadline from my website.
If you simply want to switch standard VGA modes, from text to graphics, you simply shouldn't get out of Protected Mode just for that.

Configuring the standard VGA card to enter video modes is very easy, you just need all of the data and code necessary (a few Kilobytes of Assembly code).



I will be providing a lot of code to switch mode without the BIOS since today until I finish it. I want to make easy to switch modes 3h, 4h, 12h, 13h and Mode X without complications and leave it documented once and for all to use it immediately and to read it and understand it gradually.

I want to make it the easiest to find the configuration for all standard modes and how to apply it once and for all, putting the highly commented code upfront and then the basic explanations of what it does (I will have to use several books to base and improve that code too).
Last edited by ~ on Sun May 29, 2016 8:29 pm, edited 3 times in total.
User avatar
neon
Member
Member
Posts: 1567
Joined: Sun Feb 18, 2007 7:28 pm
Contact:

Re: I can't switch back to real mode properly

Post by neon »

Hello,
Not sure what did you mean by that "i didn't addressed" your questions regarding GDT
To quote what I wrote before:
Do you know what all of the fields in the GDT entries actually are? Have you read what was provided to you? Was there any questions or doubts that you had regarding what you read?
The reason why I am asking is because you don't appear to understand what the GDT is for. So I am trying to get to the root of the problem here: Did you not read the article provided? Was there anything you were not sure about?
Hmmm... Is there any way to switch to any non-outdated graphical mode without using any interrupts or using real mode which isn't Bochs Graphics Adapter?
Sure. If you have an embedded controller or external graphics card and an Intel motherboard, get its datasheet and program it directly. Or, get the video card information from some emulator and program it directly. In the former case (writing a driver for your specific hardware) you'll be on your own and at your own risk. In the latter case (writing a driver for a device used by an emulator) you can get working source for Virtual Box, QEmu, Bochs, etc and am sure many people here worked with it before.

In short, you'll have to either use real mode, virtual 8086 mode, or custom drivers. There is the VBE protected mode interface, but it is not well supported and as addressed before by Brendan, when UEFI takes over your VBE code will no longer work.
I mean, can VESA be loaded without using interrupts or real mode?
Again, there is the protected mode interface but its not well supported. Your only real options are real or virtual 8086 mode.
OS Development Series | Wiki | os | ncc
char c[2]={"\x90\xC3"};int main(){void(*f)()=(void(__cdecl*)(void))(void*)&c;f();}
Post Reply