;Real Flat Mode

comment |

It's just Real-Mode with a little change. In Protected Mode ju don't have
really Segment-registers. A segment register in protected mode points just to
a entry in the GDT (global descriptor table). From there the information about
base-address, limit, access rights, etc. is taken and copied into a special
register, called shadow ram register. Per segment register (ES, DS, FS, ...)
one shadow ram register exists. Your real-flat-model init switches into
protected mode, loads the information about your datasegments into the
shadow-ram-register and comes back into real-mode. The special thing is, that
everything is like real-mode, just the shadow-ram-registers have their old
contense (your entrys !) from pm. Now feel free to access your memory. Things
like :

         xor    ax, ax
         mov    es, ax
         mov    edi, 0b8000h
         mov    al, '!'
         db     67h
         stosb

work !  You will trap in V86 mode if you try it.

|

;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
;Ę³žĘĶµ Protected Mode Library for RFMI ĘĶĶĶĶĶĶĶĶĶĶĶ³Ę³ v1.0 revision 0 ³µ³Ķµ
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
;
;           (C)OPYRIGHT BY PATRICK HELLWIG, ALL RIGHTS RESERVED
;
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ

.model small
.486p
.stack 50h
.code

jmp     start

DESCRIPTOR STRUC
             Limit00_15 dw      ?
             Base00_15  dw      ?
             Base16_23  db      ?
             Data1      db      ?       ;P,DPL,S,Type,Base23_16
             Data2      db      ?       ;G,D,O,AVL,Limit19_16
             Base24_31  db      ?
DESCRIPTOR ENDS

GDTR LABEL FWORD
             GDT_SIZE   dw      offset END_GDT - offset GDT     ;GDT-SegLimit
             GDT_BASE   dd      ?                               ;GDT-Address
END_GDTR LABEL

GDT LABEL
             D0         DESCRIPTOR      <?,?,?,?,?,?>           ;Dummy
             D1         DESCRIPTOR      <0ffffh,0,0,10010010b,11001111b,0>
END_GDT LABEL

init_pm proc
                mov      ax,  cs        ;get current codesegment
                and     eax, 0FFFFh     ;empty the upper 16bits
                shl     eax,   4        ;shift the segment by 4 to get the
                mov      bx, offset gdt ;real address
                and     ebx, 0FFFFh     ;now get the offset of the gdt to
                add     eax, ebx        ;calculate the 24bit address of GDT
                mov     GDT_BASE, eax
                LGDT    GDTR            ;Load GDT into GDTR
                cli
                mov     eax, cr0
                or      eax,   1        ;Enable PE-bit -> enable PM
                mov     cr0, eax
                jmp     start_PM        ;important!
start_PM:       mov      ax, 8          ;Load our segment registers
                mov      ds, ax         ;with the predefined values for
                mov      es, ax         ;real flat model
                mov      fs, ax
                mov      gs, ax
                mov     eax, cr0
                and     eax, not 1      ;Disable PE-bit -> disable PM
                mov     cr0, eax
                jmp     exit_PM         ;Important!
exit_PM:
                xor      ax, ax         ;Now zero our segmentregisters
                mov      ds, ax         ;Thats important for the use of
                mov      es, ax         ;32bit addresses in Realmode !
                mov      fs, ax         ;If we don't set them to 0, the
                mov      gs, ax         ;address of the segmentregisters
                sti                     ;would be added to the 32bit address
                ret                     ;in, fe. esi !
endp init_pm

start:  call    init_pm
        xor     ax, ax
        mov     es, ax
        mov     edi, 0b8000h
        mov     al, '!'
        mov     es:[edi], al
        mov     ah, 4ch
        int     21h
end start

