🚀 go-pugleaf

RetroBBS NetNews Server

Inspired by RockSolid Light RIP Retro Guy

Article View: alt.msdos.programmer
Article #1392

Re: How to enter Protected Mode from Assembly. 1 Q.

#1392
From: Leon Garde
Date: Fri, 06 May 1994 10:36
386 lines
12617 bytes
sir@usage.csd.unsw.OZ.AU (SIR P/L) writes:


>Hello everybody,

>		I would be *most* grateful if anyone could take a look at it
>and give me some idea what I'm doing wrong.  It simply hangs the machine, and
>the top left-hand corner of the screen remains un-changed.

>	Alternativly, if anyone has a tiny .EXE or .COM program to (1) switch
>the CPU into protected mode, and (2) execute some trivial instructions in an
>endless loop, I'd love to get a copy.  I'm much better with .ASM when I've got
>some working code to disect.
There's a small program  (  that actually returns to real mode /dos
ok.) at the end of this article. It merely writes the attribute
byte of the colour text screen (80x25 mode) in protected mode.

>		All help grately appreciated.

>Chris.
>sir@usage.csd.unsw.oz.au




>PAGE         ,132                        ;Wide output
>TITLE        Empty .EXE skeleton for protected mode
>.RADIX       16                          ;Numbers I type in are HEX by default
>INCLUDE      MACROS.ASM                  ;My pre-built functions
>SKEL         segment para public 'CODE'  ;Where the stuff will be starting from
>             public START
>             assume CS:SKEL, DS:DATA, ES:DATA, SS:STACK
>.486p        ;Allow protected-mode and 486 instructions.

>;�������������������������������������������������������������������������������

>PE_FLAG      equ     1
>data_selc    equ     20h

>;�������������������������������������������������������������������������������

>CLR     macro reg    ;This is here because I'm a 6809 veteran and
>        sub reg,reg  ;It's a beautiful macro, so why not ? (sub faster than xor)
>        endm

>;�������������������������������������������������������������������������������

>DATA         segment para public 'DATA'  ;Will be placed directly after the CODE
>gdt_desc     qword ?
>gdt_tab      dw 0,0,0,0
>             dw 0FFFFh,0,9200h,8Fh
		this segment's selector is '0b001000' ??
		thus you want to load '8' into protected mode ds.
>             dq 0
>Intro        db      'Switching into Linear protected-mode now.$'
>DATA         ends

>;�������������������������������������������������������������������������������

>STACK_SIZE   equ     1000h
>STACK        segment para stack 'STACK'  ;Will be placed directly after the DATA
>             db      (STACK_SIZE) dup(?)
>STACK        ends



>;�������������������������������������������������������������������������������
>START        proc near               ;Everything starts from here.
>PSP_SEG equ  24h
>ENV_SEG equ  2ch

>             STI                     ;enable interrupts
>             MOV     AX,DATA         ;Get the right segments pointing to 
>             MOV     DS,AX           ;the right places
>             MOV     ES,AX

>             CLR     AX
>             CLI     ;Disable interrupts
>             OUT     0A0h,AL         ;Disable NMI too

>             mov     dx,offset Intro
>             mov     ah,9
>             int     21h

>;             MOV     EAX,OFFSET GDT_DESC
>             mov     eax,offset gdt_tab
>             AND     EAX,0FFFFh
>             LGDT    fword ptr [EAX]

>             mov     ax,bx
>             or      al,pe_flag
>             lmsw    ax
on the 286 the instruction prefetch queue wouldnt be cleared here.
a far jmp instruction here should, but is it needed on a 386 ? intel
says no
>             clr     eax
>             mov     al,data_selc      
			^^^^^^^^^^  =  20h ? what entry in the gdt does
this refer to?
>             mov     ds,ax
		
>             mov     ss,ax
>             mov     es,ax
>             mov     fs,ax
>             mov     gs,ax

>             jmp     far ptr c_startup
		what does this do in protoected mode ?
	your assembler has no idea what selector to put in cs,
	it should give an error, but i guess it puts the real mode 
	value for c s there.

>             ;Exit to DOS when complete (obviously never called)
>             MOV AH,4CH
>             INT 21H
>             RET

>c_startup:   mov     esp,eax

>             mov     eax,0b8000h
>             mov     edi,eax

>             inc     dword ptr[edi]

>             MOV     AL,1
>             OUT     0A0h,AL
>             STI

>@@:          inc     dword ptr[edi]

>             jmp     @B
>             ;etc
>             hlt


>START        endp
>;�������������������������������������������������������������������������������

>SKEL         ends
>             end     START


>Chris Drake.
>sir@usage.csd.unsw.oz.au
2 problems that I saw. both extremely fatal, 
 a third is that if you've left the a20 gate on, then you are limnited
to the low 1 meg of physical addresses. turn the gate off ...
also, interrupts should be turned off, if an interrupt
occurs while they are enabled, and there isnt a valid
interrupt descriptor table then the 286/386 should 'triple fault'.
that means it returns to real mode and halts, until a further
interrupt invokes a handler that should restore the state of the
processor.

here's a program that i didnt write, it came from a book ...
it merely changes to protected mode, changes the attributes of
the colour text screen characters and returns to dos.


:r pmd.asm

;PAGE ,132

bios_data_seg SEGMENT at 0040h
        ORG 0067h

io_rom_init  dw ? ;
io_rom_seg   dw ? ;

bios_data_seg ENDS

descriptor STRUC
seg_limit       dw 0;
base_lo_word    dw 0;
base_hi_byte    db 0;
access_rights   db 0;
                dw 0;
descriptor ENDS

cmos_port equ 070h
code_seg_access equ 10011011b
data_seg_access equ 10010011b
disable_bit20   equ 11011101b
enable_bit20    equ 11011111b
inta01          equ 021h
intb01          equ 0a1h
port_a          equ 060h
shut_cmd        equ 0feh
shut_down       equ 0fh
status_port     equ 064h
virtual_enable   equ 01h

lgdt    MACRO   lgdt1
        LOCAL   lgdt2,lgdt3
        db 00fh
lgdt2   label   byte
        mov dx,word ptr lgdt1
lgdt3   label   byte
        org     offset lgdt2
        db      01h
        org     offset lgdt3
        ENDM

lmsw    MACRO lmsw1
        LOCAL lmsw2, lmsw3
        db 00fh
lmsw2   label  byte
        mov si,ax
lmsw3   label byte
        org offset lmsw2
        db 1h
        org offset lmsw3
        ENDM

jumpfar MACRO jumpfar1, jumpfar2
        db 0EAh
        dw (offset jumpfar1)
        dw jumpfar2
        ENDM

cseg SEGMENT para public 'code'
        ASSUME cs:cseg
        ORG 0100h
start:  jmp short main 
EVEN

gdt     LABEL word
gdt_desc        EQU (($-gdt)/8)*8 +0b
gdt1            descriptor      <gdt_leng,,,data_seg_access,>
cs_code         EQU (($-gdt)/8)*8 +0b
gdt2            descriptor      <cseg_leng,,,code_seg_access,>
cs_data         EQU (($-gdt)/8)*8 + 0b
gdt3            descriptor      <cseg_leng,,,data_seg_access,>
ss_desc         EQU (($-gdt)/8)*8 + 0B
gdt4            descriptor      <0FFFFh,,,data_seg_access,>
ds_desc         EQU (($-gdt)/8)*8 + 0B
gdt5            descriptor      <0FFFFh,,,data_seg_access,>
es_desc         EQU (($-gdt)/8)*8 + 0B
gdt6            descriptor      <0FFFFh,,,data_seg_access,>
gdt_leng        EQU $-gdt
PAGE
i8259_1 db ?
i8259_2 db ?

; MAIN

ASSUME ds:cseg

main PROC
        cld
        mov dx,cs
        mov cx, offset gdt
        call form_24bit_address
        mov gdt1.base_lo_word, dx
        mov gdt1.base_hi_byte, cl
        mov dx,cs
        xor cx,cx
        call form_24bit_address
        mov gdt2.base_lo_word, dx
        mov gdt2.base_hi_byte, cl
        mov gdt3.base_lo_word, dx
        mov gdt3.base_hi_byte, cl

        mov dx,ss
        xor cx,cx
        call form_24bit_address
        mov gdt4.base_lo_word, dx
        mov gdt4.base_hi_byte, cl
        lgdt gdt
        mov ah, enable_bit20
        call gate_a20
        or al,al
        jz m_10
        mov dx, offset gate_failure
        mov ah, 9
        int 21h
        int 20h
gate_failure    db "address line a20 failed to gate open$"
m_10:   cli
        in al, inta01
        mov i8259_1,al
        in al, intb01
        mov i8259_2, al

        ASSUME ds:bios_data_seg
        mov dx, bios_data_seg
        mov ds,dx
        mov io_rom_seg, cs
        mov io_rom_init, offset real
        mov al, shut_down
        out cmos_port,al
        jmp short $+2
        mov al,5
        out cmos_port+1, al
        mov ax, virtual_enable
        lmsw ax

        jumpfar m_20, cs_code

m_20:   ASSUME ds:cseg
        mov ax, ss_desc
        mov ss,ax
        mov ax, cs_data
        mov ds, ax
        mov gdt5.base_lo_word, 08000h
        mov gdt5.base_hi_byte, 0bh
        mov gdt6.base_lo_word, 08000h
        mov gdt6.base_hi_byte, 0bh
        mov ax, ds_desc
        mov ds, ax
        mov ax, es_desc
        mov es, ax
        mov cx, 80*25
        xor si,si
        xor di,di

m_30:   lodsw
        mov ah, 070h
        stosw
        loop m_30
        mov al, shut_cmd
        out status_port, al
m_40:   hlt
        jmp short m_40

gate_a20 PROC
        cli
        call  empty_8042
        jnz gate_a20_01
        mov al, 0d1h
        out status_port, al
        call empty_8042
        jnz gate_a20_01
        mov al,ah
        out port_a, al
        call empty_8042
gate_a20_01:
        ret
gate_a20 ENDP

empty_8042      PROC
        push cx
        sub cx,cx
empty_8042_01:
        in al, status_port
        and al, 010b
        loopnz empty_8042_01
        pop cx
empty_8042 ENDP

form_24bit_address PROC
        push ax
        rol dx,1
        rol dx,1
        rol dx,1
        rol dx,1
        mov ax,dx
        and dl, 0f0h
        and ax, 0fh
        add dx, cx
        mov cx, ax
        adc cl, ch
        pop ax
        ret
form_24bit_address ENDP

        ASSUME ds:cseg

real:   mov dx, cs
        mov ds, dx
        mov ah, disable_bit20
        call gate_a20
        mov al, i8259_1
        out inta01, al
        mov al, i8259_2
        out intb01, al
        sti 
        int 20h

main ENDP
cseg_leng EQU $
cseg ENDS

END start
-- 
leon garde; lgarde@scorch.hna.com.au
Technical Details
Message-ID: <1994May6.103630.2300@scorch.hna.com.au>
Path: arc1-ca.pugleaf.net!bga.com!news.sprintlink.net!hookup!ames!agate!msuinfo!harbinger.cc.monash.edu.au!newshost.anu.edu.au!sserve!usage!metro!seagoon.newcastle.edu.au!scorch!lgarde
References: <1994May5.052710.9875@usage.csd.unsw.OZ.AU>

Show Full Headers
Complete Article Headers
X-Google-Language: ENGLISH,ASCII
X-Google-Thread: 10f6aa,6994a0d4e02e984d
X-Google-Attributes: gid10f6aa,public
X-Google-Thread: ffec8,6994a0d4e02e984d
X-Google-Attributes: gidffec8,public
X-Google-Thread: 10d683,6994a0d4e02e984d
X-Google-Attributes: gid10d683,public
X-Google-Thread: fe306,6994a0d4e02e984d
X-Google-Attributes: gidfe306,public
X-Google-Thread: ff6a6,6994a0d4e02e984d
X-Google-Attributes: gidff6a6,public
X-Google-Thread: 102bfa,6994a0d4e02e984d
X-Google-Attributes: gid102bfa,public
X-Google-Thread: 10bb54,6994a0d4e02e984d
X-Google-Attributes: gid10bb54,public
X-Google-ArrivalTime: 1994-05-06 07:31:28 PST
Newsgroups: alt.msdos.programmer,alt.2600,comp.sys.ibm.pc.programmer,comp.os.msdos.programmer,rec.games.programmer,aus.computers.ibm-pc,comp.sys.ibm.pc.hardware
Path: arc1-ca.pugleaf.net!bga.com!news.sprintlink.net!hookup!ames!agate!msuinfo!harbinger.cc.monash.edu.au!newshost.anu.edu.au!sserve!usage!metro!seagoon.newcastle.edu.au!scorch!lgarde
From: lgarde@scorch.hna.com.au (Leon Garde)
Subject: Re: How to enter Protected Mode from Assembly. 1 Q.
Keywords: protected mode .ASM assembler flat 486 386
References: <1994May5.052710.9875@usage.csd.unsw.OZ.AU>
Organization: Hunter Network Association Host Machine, Newcastle OZ
Date: Fri, 6 May 1994 10:36:30 GMT
Message-ID: <1994May6.103630.2300@scorch.hna.com.au>
Lines: 386