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

  1. ;****************************************************************
  2. ;*
  3. ;*    TOMCOM.ASM -    .COM program to relax segment limit on GS in
  4. ;*            real-address mode.
  5. ;*
  6. ;*    Assembled using Microsoft Macro Assembler 5.1
  7. ;*
  8. ;****************************************************************
  9.  
  10. ;*    Need to use 80386 protected mode instructions
  11.     .386P
  12.  
  13. ;
  14. ;    JUMPFAR does a far jump in USE16 segments
  15. ;
  16. JUMPFAR MACRO    PARM1,PARM2
  17.     DB    0EAH            ; jump far direct
  18.     DW    (OFFSET PARM1)        ; to this offset
  19.     DW    PARM2            ; in this segment
  20.     ENDM
  21.  
  22. CMOS_ADDR        EQU    0070H
  23. CMOS_DATA        EQU    0071H
  24.  
  25. SYS_PROT_CS        EQU    0008H
  26. SYS_REAL_SEG        EQU    0010H
  27. SYS_MONDO_SEG        EQU    0018H
  28.  
  29. cr        equ    0dh
  30. lf        equ    0ah
  31. dos_call    equ    21h
  32. print_func    equ    09h
  33.  
  34. cseg    segment    use16 public    'code'
  35.     assume    cs:cseg,ds:cseg,es:cseg,ss:cseg
  36.  
  37.     org    100h
  38. begin:
  39. ;
  40. ;    Setup Environment
  41. ;
  42.         mov    sp,offset stk_top        ; setup stack
  43.         mov    ax,cs                ; store program segment
  44.  
  45. ;    WARNING:  Self-modifying code.  Not needed if done in ROM.
  46.         mov    word ptr cs:self_mod_cs,ax
  47.  
  48.         mov    ds,ax                ; set ds := cs
  49.         jmp    init_com            ; go do the work
  50.     
  51. ;---------------------------------------------------------------
  52. ;
  53. ;    Variables
  54. ;
  55. ;---------------------------------------------------------------
  56. com_gdt_ptr    dq    ?                ; for LGDT
  57. ;            Limit    Base    Rights    LimitHi
  58. com_gdt        dw    00000h, 00000h, 00000h, 00000h    ; unusable
  59.         dw    0FFFFh, 00000h, 09A00h, 00000h    ; code seg
  60.         dw    0FFFFh, 00000h, 09200h, 00000h    ; data seg
  61.         dw    0FFFFh, 00000h, 09200h, 0008Fh    ; mondo seg (4Gb)
  62. com_gdt_end    label    word
  63. ;---------------------------------------------------------------
  64.  
  65. load_msg    db    'Segment Helper Loaded',cr,lf
  66.         db    'Use extended register and GS: to activate',cr,lf,'$'
  67.  
  68. fixup_Msg    db    'System Altered',cr,lf,'$'
  69.  
  70.         db    255 dup(0ffh)            ;local stack
  71. stk_top        db           (0ffh)    
  72.  
  73.  
  74.  
  75. ;****************************************************************
  76. ;*    Go to protected mode to relax limit on GS        *
  77. ;*    Entry    -    none
  78. ;*    Exit    -    gs: invisible selector information fixed up
  79. ;*            ds & ss: set to cs (ok for COM file)
  80. ;*    WARNING:    MUST EXECUTE BELOW 1M, GATE A20 NOT DISABLED
  81. ;****************************************************************
  82. kill_seg_limit    proc    near
  83.  
  84.         mov    ax, cs                ; get linear address
  85.         movzx    eax, ax
  86.         shl    eax,4
  87.  
  88.         mov    ebx, eax            ; store copy of CS linear
  89.         mov    word ptr cs:com_gdt+10, ax    ; store in code segment desc
  90.         mov    word ptr cs:com_gdt+18, ax    ; store in data segment desc
  91.         ror    eax, 16                ; swap words
  92.         mov    byte ptr cs:com_gdt+12, al    ; bits 16-23
  93.         mov    byte ptr cs:com_gdt+20, al    ; bits 16-23
  94. ;
  95. ;    Setup Limit and Base for GDTR
  96. ;
  97.         add    ebx, offset com_gdt
  98.         mov    word ptr cs:com_gdt_ptr, (offset com_gdt_end - com_gdt - 1)
  99.         mov    dword ptr cs:com_gdt_ptr+2, ebx
  100.  
  101. ;    store flags for restoring after cli
  102.         pushf
  103. ;    do NOT allow interrupts as IDT is not valid in protected mode
  104.         cli
  105. ;    disable NMI's here
  106.         in    al,CMOS_ADDR
  107.         mov    ah,al
  108.         or    al, 080H        ; don't disturb rest of 70
  109.         out    CMOS_ADDR, al
  110.         and    ah, 080H
  111.         mov    ch, ah            ; store old state of NMI mask
  112.  
  113.         lgdt    fword ptr cs:com_gdt_ptr    ; assume DOS isn't using this
  114.  
  115.         mov    bx, cs            ; save com segment
  116.  
  117.         mov    eax,cr0
  118.         or    al,01            ; set PE bit
  119.         mov    cr0,eax            ; protection enabled
  120.         jumpfar    ksl_pmode,SYS_PROT_CS    ; purge queue and fix CS
  121.  
  122. ksl_pmode:
  123.         mov    ax, SYS_REAL_SEG    ; prepare limits on segments
  124.         mov    ss, ax
  125.         mov    ds, ax
  126.         mov    es, ax
  127.         mov    fs, ax
  128. ;
  129. ;    Here are the instructions that makes it all possible
  130. ;
  131.         mov    ax, SYS_MONDO_SEG        ; gs will now be 4G
  132.         mov    gs, ax
  133.         
  134.         mov    eax,cr0
  135.         and    al,NOT 01        ; clear PE bit
  136.         mov    cr0,eax            ; protection disabled
  137. ;
  138. ;    the following relies on self-modification performed at beginning
  139. ;    of program.  The following macro would be useful here for ROM code only, 
  140. ;    so it is manually expanded to facilitate the (yech) self-modification.
  141. ;
  142. ;        jumpfar    ksl_rmode,SYS_REAL_CSEG    ; purge queue and fix CS
  143. ;
  144.         DB    0EAH            ; jump far direct
  145.         DW    (OFFSET ksl_rmode)    ; to this offset
  146. ;    (please don't send me to programmer's hell for this one)
  147. self_mod_cs    DW    ?            ; in this segment
  148. ksl_rmode:
  149.         mov    ss, bx            ; get seg regs back
  150.         mov    ds, bx
  151.         xor    ax, ax            ; clear unused to be cleanly
  152.         mov    es, ax
  153.         mov    fs, ax
  154.         mov    gs, ax
  155. ;
  156. ;    back in Real Mode, IDT is ok again
  157. ;
  158.         in    al,CMOS_ADDR
  159.         and    al, 07FH
  160.         or    al, ch            ; restore old state of NMI mask
  161.         out    CMOS_ADDR, al
  162. ;
  163. ;    note that 386 does not have POPF problem
  164. ;
  165.         popf                ; restore IRQ mask
  166.  
  167.         ret
  168.  
  169. kill_seg_limit    endp
  170.  
  171.  
  172.  
  173. ;**************************************************************
  174. ;*    Main Control Routine Starts Here              *
  175. ;**************************************************************
  176. initialize    proc    near
  177.     assume    ds:cseg
  178. ;
  179. init_com:
  180.  
  181. ;display message and then relax limit checking on GS
  182. ;
  183.     mov    dx,offset load_msg
  184.     mov    ah,print_func
  185.     int    dos_call
  186. ;
  187. ; fix gs
  188. ;
  189.     call    kill_seg_limit
  190.  
  191.     mov    dx,offset fixup_Msg
  192.     mov    ah,print_func
  193.     int    dos_call
  194. ;
  195. ;check amount of memory to retain
  196. ;
  197.     mov    ax,4C00h    ;Terminate with return code function
  198.     int    dos_call
  199. ;
  200. initialize    endp
  201. ;----------------------------------------------------------
  202.  
  203.  
  204. cseg    ends
  205.     end    begin
  206.