Going back into real mode...

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.
Post Reply
EclipseOS

Going back into real mode...

Post by EclipseOS »

Hey, I have an assembly code that I need to run  on my os, but I can;t run it in protected mode, does anyone have some code on going back into real mode? Thanx alot for your help. I need it to use int 15 to poweroff the computer.
GT

RE:Going back into real mode...

Post by GT »

I used to switch back to real mode for making BIOS calls, then back to protected mode when done.  I no longer do this as I now have a working Virtual-8086 mode, but here's the snatch of code I used to use to drop down to real mode from protected mode.  It follows the procedure described in the IA-32 Intel Architecture Software Developer's Manual, Volume 3: System Programming Guide.  The comments refer to the sections in that manual.  0x0008 is a 16-bit code segment and 0x0010 a 16-bit data segment in my GDT.  The code enters from 32-bit protected mode, kicks down into 16-bit protected mode, and finally switches into real mode.  The 16-bit pmode steps are necessary to set the hidden upper bits of the segment selectors properly -- otherwise you end up in "unreal mode" (which can be fun but probably isn't what you want).

; See IA-32 Dev vol 3 sec 8.9.2 & 1 for explanation of steps mentioned below

        cli                             ; 8.9.2. Step 1.

        mov     eax,cr0                 ; 8.9.2. Step 2.
        and     eax,0x7FFFFFFF
        mov     cr0,eax
        xor     eax,eax
        mov     cr3,eax

        jmp     0x0008:.prot16          ; 8.9.2. Step 3.
[bits 16]
.prot16 nop

        mov     ax,0x0010               ; 8.9.2. Step 4.
        mov     ds,ax
        mov     es,ax
        mov     fs,ax
        mov     gs,ax
        mov     ss,ax

        mov     ax,0x03FF               ; 8.9.2. Step 5.
        mov     [newidt],ax
        xor     ax,ax
        mov     [newidt+2],ax
        mov     [newidt+4],ax
        lidt    [newidt]

        mov     eax,cr0                 ; 8.9.2. Step 6.
        and     eax,0xFFFFFFFE
        mov     cr0,eax

        jmp     dword 0x0000:.real16    ; 8.9.2. Step 7.
.real16 nop

        xor     ax,ax                   ; 8.9.2. Step 8.
        mov     ds,ax
        mov     es,ax
        mov     fs,ax
        mov     gs,ax
        mov     ss,ax

        sti                             ; 8.9.2. Step 9.
EclipseOS

RE:Going back into real mode...

Post by EclipseOS »

Hey thanx for your reply! I forgot about this post until I was searching for help on this and it came up on google. The one problem that I am having with your code is:

What is newidt? Nasm comes up with an error. Thanx alot again!

Brandon Holland
GT

RE:Going back into real mode...

Post by GT »

Ah, forgot about that, it's defined elsewhere, it's actually just 6 bytes of memory, could be anywhere...  here's where it's defined:

newidt  equ     0x632

You could just as easily use:

newidt  dw      0
        dd      0

In my case I was using specific defined addresses in lower memory to exchange data between real mode assembly and pmode C, so I just threw newidt in with all the other defines.  As the code sets the values before using it, it doesn't actually need to be initialized to zeroes...
Post Reply