home *** CD-ROM | disk | FTP | other *** search
- ;****************************************************************
- ;*
- ;* TOMCOM.ASM - .COM program to relax segment limit on GS in
- ;* real-address mode.
- ;*
- ;* Assembled using Microsoft Macro Assembler 5.1
- ;*
- ;****************************************************************
-
- ;* Need to use 80386 protected mode instructions
- .386P
-
- ;
- ; JUMPFAR does a far jump in USE16 segments
- ;
- JUMPFAR MACRO PARM1,PARM2
- DB 0EAH ; jump far direct
- DW (OFFSET PARM1) ; to this offset
- DW PARM2 ; in this segment
- ENDM
-
- CMOS_ADDR EQU 0070H
- CMOS_DATA EQU 0071H
-
- SYS_PROT_CS EQU 0008H
- SYS_REAL_SEG EQU 0010H
- SYS_MONDO_SEG EQU 0018H
-
- cr equ 0dh
- lf equ 0ah
- dos_call equ 21h
- print_func equ 09h
-
- cseg segment use16 public 'code'
- assume cs:cseg,ds:cseg,es:cseg,ss:cseg
-
- org 100h
- begin:
- ;
- ; Setup Environment
- ;
- mov sp,offset stk_top ; setup stack
- mov ax,cs ; store program segment
-
- ; WARNING: Self-modifying code. Not needed if done in ROM.
- mov word ptr cs:self_mod_cs,ax
-
- mov ds,ax ; set ds := cs
- jmp init_com ; go do the work
-
- ;---------------------------------------------------------------
- ;
- ; Variables
- ;
- ;---------------------------------------------------------------
- com_gdt_ptr dq ? ; for LGDT
- ; Limit Base Rights LimitHi
- com_gdt dw 00000h, 00000h, 00000h, 00000h ; unusable
- dw 0FFFFh, 00000h, 09A00h, 00000h ; code seg
- dw 0FFFFh, 00000h, 09200h, 00000h ; data seg
- dw 0FFFFh, 00000h, 09200h, 0008Fh ; mondo seg (4Gb)
- com_gdt_end label word
- ;---------------------------------------------------------------
-
- load_msg db 'Segment Helper Loaded',cr,lf
- db 'Use extended register and GS: to activate',cr,lf,'$'
-
- fixup_Msg db 'System Altered',cr,lf,'$'
-
- db 255 dup(0ffh) ;local stack
- stk_top db (0ffh)
-
-
-
- ;****************************************************************
- ;* Go to protected mode to relax limit on GS *
- ;* Entry - none
- ;* Exit - gs: invisible selector information fixed up
- ;* ds & ss: set to cs (ok for COM file)
- ;* WARNING: MUST EXECUTE BELOW 1M, GATE A20 NOT DISABLED
- ;****************************************************************
- kill_seg_limit proc near
-
- mov ax, cs ; get linear address
- movzx eax, ax
- shl eax,4
-
- mov ebx, eax ; store copy of CS linear
- mov word ptr cs:com_gdt+10, ax ; store in code segment desc
- mov word ptr cs:com_gdt+18, ax ; store in data segment desc
- ror eax, 16 ; swap words
- mov byte ptr cs:com_gdt+12, al ; bits 16-23
- mov byte ptr cs:com_gdt+20, al ; bits 16-23
- ;
- ; Setup Limit and Base for GDTR
- ;
- add ebx, offset com_gdt
- mov word ptr cs:com_gdt_ptr, (offset com_gdt_end - com_gdt - 1)
- mov dword ptr cs:com_gdt_ptr+2, ebx
-
- ; store flags for restoring after cli
- pushf
- ; do NOT allow interrupts as IDT is not valid in protected mode
- cli
- ; disable NMI's here
- in al,CMOS_ADDR
- mov ah,al
- or al, 080H ; don't disturb rest of 70
- out CMOS_ADDR, al
- and ah, 080H
- mov ch, ah ; store old state of NMI mask
-
- lgdt fword ptr cs:com_gdt_ptr ; assume DOS isn't using this
-
- mov bx, cs ; save com segment
-
- mov eax,cr0
- or al,01 ; set PE bit
- mov cr0,eax ; protection enabled
- jumpfar ksl_pmode,SYS_PROT_CS ; purge queue and fix CS
-
- ksl_pmode:
- mov ax, SYS_REAL_SEG ; prepare limits on segments
- mov ss, ax
- mov ds, ax
- mov es, ax
- mov fs, ax
- ;
- ; Here are the instructions that makes it all possible
- ;
- mov ax, SYS_MONDO_SEG ; gs will now be 4G
- mov gs, ax
-
- mov eax,cr0
- and al,NOT 01 ; clear PE bit
- mov cr0,eax ; protection disabled
- ;
- ; the following relies on self-modification performed at beginning
- ; of program. The following macro would be useful here for ROM code only,
- ; so it is manually expanded to facilitate the (yech) self-modification.
- ;
- ; jumpfar ksl_rmode,SYS_REAL_CSEG ; purge queue and fix CS
- ;
- DB 0EAH ; jump far direct
- DW (OFFSET ksl_rmode) ; to this offset
- ; (please don't send me to programmer's hell for this one)
- self_mod_cs DW ? ; in this segment
- ksl_rmode:
- mov ss, bx ; get seg regs back
- mov ds, bx
- xor ax, ax ; clear unused to be cleanly
- mov es, ax
- mov fs, ax
- mov gs, ax
- ;
- ; back in Real Mode, IDT is ok again
- ;
- in al,CMOS_ADDR
- and al, 07FH
- or al, ch ; restore old state of NMI mask
- out CMOS_ADDR, al
- ;
- ; note that 386 does not have POPF problem
- ;
- popf ; restore IRQ mask
-
- ret
-
- kill_seg_limit endp
-
-
-
- ;**************************************************************
- ;* Main Control Routine Starts Here *
- ;**************************************************************
- initialize proc near
- assume ds:cseg
- ;
- init_com:
-
- ;display message and then relax limit checking on GS
- ;
- mov dx,offset load_msg
- mov ah,print_func
- int dos_call
- ;
- ; fix gs
- ;
- call kill_seg_limit
-
- mov dx,offset fixup_Msg
- mov ah,print_func
- int dos_call
- ;
- ;check amount of memory to retain
- ;
- mov ax,4C00h ;Terminate with return code function
- int dos_call
- ;
- initialize endp
- ;----------------------------------------------------------
-
-
- cseg ends
- end begin
-