.386p


gdt_desc STRUC
  limit		DW	?
  base_lw	DW	?
  base_hwlb	DB	?
  access	DB	?
  limit&access	DB	0
  base_hwhb	DB	0
gdt_desc ENDS

idt_desc STRUC
  offset_lw	DW	?
  sel		DW	?
  _reserved	DB	0
  access	DB	?
  offset_hw	DW	0
idt_desc ENDS

dt_load STRUC
  limit		DW	?
  addr32	DD	?
dt_load ENDS

cs_access	EQU	10011010b
ds_access	EQU	10010010b


cseg SEGMENT Para USE16 public 'code'
     ASSUME cs:cseg,ds:cseg
     ORG 100h

start:

  xor	ebx,ebx
  mov	bx,cs
  mov	seg_rm,bx
  shl	ebx,4

  mov	eax,ebx
  mov	gdt_cs.base_lw,ax
  mov	gdt_ds.base_lw,ax
  shr	eax,16
  mov	gdt_cs.base_hwlb,al
  mov	gdt_ds.base_hwlb,al

  lea	eax,gdt
  add	eax,ebx
  mov	gdt_load.addr32,eax
  lea	eax,idt
  add	eax,ebx
  mov	idtpm_load.addr32,eax

  cli
  mov	al,80h
  out	70h,al

  lgdt	gdt_load
  lidt	idtpm_load

  mov	eax,cr0
  or	eax,1
  mov	cr0,eax
  DB	0EAh
  DW	protect
  DW	cs_sel

protect: 

  mov	ax,ds_sel
  mov	ss,ax
  mov	ds,ax
  mov	ax,video_sel
  mov	es,ax

  mov	ah,4eh
  lea	si, msg_pm
  mov	di,160
  mov	cx,msglen_pm
@@r:
  lodsb
  stosw
  loop	@@r
  int	29d

  mov	ax,ds_sel
  mov	es,ax

  mov	eax,cr0
  and	eax,0FFFFFFFEh
  mov	cr0,eax
  DB	0EAh
  DW	real
 seg_rm	DW ?

real:

  lidt	idtrm_load
  mov	ax,cs
  mov	ds,ax
  mov	ss,ax
  mov	es,ax

  sti
  mov	al,0
  out	70h,al

  mov	ah,09h
  lea	dx,msg_rm
  int	21h
  ret

ex0_proc:  iretd
ex1_proc:  iretd
ex2_proc:  iretd
ex3_proc:  iretd
ex4_proc:  iretd
ex5_proc:  iretd
ex6_proc:  iretd
ex7_proc:  iretd
ex8_proc:  iretd
ex9_proc:  iretd
ex10_proc: iretd
ex11_proc: iretd
ex12_proc: iretd
ex13_proc: iretd
ex14_proc: iretd
ex15_proc: iretd
ex16_proc: iretd
ex17_proc: iretd
ex18_proc: iretd

int29_proc PROC

  in	al,61h
  push	ax

b20:

  mov	dx,durtion

b30:

  and	al,11111100b
  out	61h,al
  mov	cx,tone

b40: loop b40

  or	al,00000010b
  out	61h,al
  mov	cx,tone

b50: loop b50

  dec	dx
  jnz	b30
  shl	durtion,1
  shr	tone,1
  jnz	b20
  
  pop	ax
  out	61h,al

  iretd

int29_proc ENDP


 gdt label
  null_sel	EQU $-gdt
  gdt_null	gdt_desc<0,0,0,0,0>

  cs_sel	EQU $-gdt
  gdt_cs	gdt_desc<0FFFFh,,,cs_access,,>

  ds_sel	EQU $-gdt
  gdt_ds	gdt_desc<0FFFFh,,,ds_access,,>

  video_sel	EQU $-gdt
  gdt_video	gdt_desc<0FFFh,8000h,0Bh,ds_access,,>
 gdt_len	EQU $-gdt

 idt label
  ex0	idt_desc<ex0_proc,cs_sel,,8fh,>
  ex1	idt_desc<ex1_proc,cs_sel,,8fh,>
  ex2	idt_desc<ex2_proc,cs_sel,,8eh,>
  ex3	idt_desc<ex3_proc,cs_sel,,8fh,>
  ex4	idt_desc<ex4_proc,cs_sel,,8fh,>
  ex5	idt_desc<ex5_proc,cs_sel,,8fh,>
  ex6	idt_desc<ex6_proc,cs_sel,,8fh,>
  ex7	idt_desc<ex7_proc,cs_sel,,8fh,>
  ex8	idt_desc<ex8_proc,cs_sel,,8fh,>
  ex9	idt_desc<ex9_proc,cs_sel,,8fh,>
  ex10	idt_desc<ex10_proc,cs_sel,,8fh,>
  ex11	idt_desc<ex11_proc,cs_sel,,8fh,>
  ex12	idt_desc<ex12_proc,cs_sel,,8fh,>
  ex13	idt_desc<ex13_proc,cs_sel,,8fh,>
  ex14	idt_desc<ex14_proc,cs_sel,,8fh,>
  ex15	idt_desc<ex15_proc,cs_sel,,8fh,>
  ex16	idt_desc<ex16_proc,cs_sel,,8fh,>
  ex17	idt_desc<ex17_proc,cs_sel,,8fh,>
  ex18	idt_desc<ex18_proc,cs_sel,,8fh,>
	idt_desc 10 dup(<>)
  int29 idt_desc<int29_proc,cs_sel,,8eh,>
 idt_len	EQU $-idt


  gdt_load	dt_load<gdt_len-1,>
  idtpm_load	dt_load<idt_len-1,>
  idtrm_load	dt_load<3FFh,0>


  msg_pm	DB	'Protected Mode'
  msglen_pm	EQU	$-msg_pm
  msg_rm	DB	'Real Mode$'

  durtion	DW	1000
  tone		DW	256H

cseg ENDS

END start
