Article View: alt.msdos.programmer
Article #1392Re: How to enter Protected Mode from Assembly. 1 Q.
From: Leon Garde
Date: Fri, 06 May 1994 10:36
Date: Fri, 06 May 1994 10:36
386 lines
12617 bytes
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!lgardeReferences:
<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