home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Simtel MSDOS 1992 September
/
Simtel20_Sept92.cdr
/
msdos
/
progjorn
/
pj_7_6.arc
/
TOMCOM.ASM
< prev
next >
Wrap
Assembly Source File
|
1989-07-31
|
5KB
|
206 lines
;****************************************************************
;*
;* 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