home *** CD-ROM | disk | FTP | other *** search
/ The C Users' Group Library 1994 August / wc-cdrom-cusersgrouplibrary-1994-08.iso / listings / v_02_10 / 2n10046a < prev    next >
Text File  |  1991-01-29  |  21KB  |  632 lines

  1.     Page    60,132
  2. ;---------------------------------------------------------------
  3. ;               BEGIN LISTING 3
  4. ;---------------------------------------------------------------
  5. ;
  6. ; EMULOAD.ASM    Copyright (c) 1991 Robert Collins
  7. ;
  8. ;    This utility uses '386 LOADALL to emulate '286 LOADALL.
  9. ;    All 16-bit registers are zero-extended to 32-bit
  10. ;    registers.  All 24-bit physical addresses are zero-
  11. ;    extended to 32-bit registers.  '386-specific registers
  12. ;    not used in '286 LOADALL are either set to the current
  13. ;    values (Debug registers), or zeroed (segment registers).
  14. ;
  15. ;---------------------------------------------------------------
  16. ;
  17. ;    This program assumes that you have run the '386 LOADALL
  18. ;    test prior to installing this TSR.  Obviously if LOADALL
  19. ;    has been removed from the '386 mask, then this program
  20. ;    will never work.  Likewise, it is easier for me to
  21. ;    document the need to run the LOADALL test program, than
  22. ;    to incorporate it into this code.
  23. ;
  24. ;---------------------------------------------------------------
  25. ;
  26. ;    EMULOAD returns ERROR codes to DOS that can be
  27. ;    intecepted by the batch file command 'IF ERRORLEVEL'.
  28. ;    The following ERRORLEVEL codes are generated by this
  29. ;    program:
  30. ;      0 = EMULOAD driver now installed in memory
  31. ;      1 = Attempted removal of the EMULOAD driver from
  32. ;          memory failed because EMULOAD was not in already
  33. ;          in memory.
  34. ;      2 = The EMULOAD driver was already in memory when an
  35. ;          attempt was made to install it again.
  36. ;      3 = Bogus command line argument(s).
  37. ;      4 = Help requested.
  38. ;      5 = The EMULOAD driver was sucessfully removed from
  39. ;          memory.
  40. ;      6 = Can't install the EMULOAD driver because this
  41. ;          computer isn't an 80386.
  42. ;
  43. ;---------------------------------------------------------------
  44. ;
  45. ;    Compilation instructions:
  46. ;        MASM EMULOAD;        (MASM 5.1)
  47. ;        LINK EMULOAD;
  48. ;        EXE2BIN EMULOAD EMULOAD.COM
  49. ;        DEL EMULOAD.EXE
  50. ;
  51. ;    The resultant EMULOAD.COM file is 1473 bytes, while the
  52. ;    TSR portion is 1072 bytes.
  53. ;
  54. ;---------------------------------------------------------------
  55. ; Compiler directives
  56. ;---------------------------------------------------------------
  57.     Title    EMULOAD
  58.     .radix    16
  59.     .8086
  60.  
  61. ;---------------------------------------------------------------
  62. ; Interrupt vector segment
  63. ;---------------------------------------------------------------
  64. ABS0    segment at 0
  65.     org 6*4
  66.     INT_6    dd    ?
  67.  
  68.     org 800h
  69.     Loadall_286    dd    ?
  70. ABS0    ends
  71.  
  72.  
  73. ;---------------------------------------------------------------
  74. ; Structure definitions
  75. ;---------------------------------------------------------------
  76. Desc_cache2    STRUC            ; 80286 Descriptor cache
  77.     A15_A00 dw    ?        ;  register layout.
  78.     A23_A16 db    ?
  79.     _Type2    db    ?
  80.     _Limit2 dw    ?
  81. Desc_cache2    ENDS
  82.  
  83.  
  84. Desc_cache3    STRUC            ; 80386 Descriptor cache
  85.     _Access db    0        ;  register layout
  86.     _Type    db    ?
  87.     _CS32    db    0
  88.         db    0
  89.     _Addr    dd    ?
  90.     _Limit    dd    ?
  91. Desc_cache3    ENDS
  92.  
  93.  
  94.  
  95. Loadall_struc2    STRUC            ; 80286 LOADALL table
  96.             dw    3 dup (?)    ; RESERVED
  97.     _286Msw     dw    ?        ; MSW
  98.             dw    7 dup (?)    ; RESERVED
  99.     _286Tr        dw    ?        ; TR
  100.     _Flags        dw    ?        ; FLAGS
  101.     _286Ip        dw    ?        ; IP
  102.     _286Ldt     dw    ?        ; LDT
  103.     _286Ds        dw    ?        ; DS
  104.     _286Ss        dw    ?        ; SS
  105.     _286Cs        dw    ?        ; CS
  106.     _286Es        dw    ?        ; ES
  107.     _286Di        dw    ?        ; DI
  108.     _286Si        dw    ?        ; SI
  109.     _286Bp        dw    ?        ; BP
  110.     _286Sp        dw    ?        ; SP
  111.     _286Bx        dw    ?        ; BX
  112.     _286Dx        dw    ?        ; DX
  113.     _286Cx        dw    ?        ; CX
  114.     _286Ax        dw    ?        ; AX
  115.     ES_Desc286    dw    3 dup (?)    ; ES Desc. Cache
  116.     CS_Desc286    dw    3 dup (?)    ; CS Desc. Cache
  117.     SS_Desc286    dw    3 dup (?)    ; SS Desc. Cache
  118.     DS_Desc286    dw    3 dup (?)    ; DS Desc. Cache
  119.     Gdt_Desc286    dw    3 dup (?)    ; GDTR
  120.     Ldt_Desc286    dw    3 dup (?)    ; LDTR
  121.     Idt_Desc286    dw    3 dup (?)    ; IDTR
  122.     TSS_Desc286    dw    3 dup (?)    ; TSSR
  123. Loadall_Struc2    ENDS
  124.  
  125. Loadall_struc3    STRUC
  126.     _Cr0        dd    ?        ; EAX
  127.     _Eflags     dd    ?        ; EFLAGS
  128.     _Eip        dd    ?        ; EIP
  129.     _Edi        dd    ?        ; EDI
  130.     _Esi        dd    ?        ; ESI
  131.     _Ebp        dd    ?        ; EBP
  132.     _Esp        dd    ?        ; ESP
  133.     _Ebx        dd    ?        ; EBX
  134.     _Edx        dd    ?        ; EDX
  135.     _Ecx        dd    ?        ; ECX
  136.     _Eax        dd    ?        ; EAX
  137.     _Dr6        dd    ?        ; DR6
  138.     _Dr7        dd    ?        ; DR7
  139.     _Tr        dd    ?        ; TR
  140.     _Ldt        dd    ?        ; LDT
  141.     _Gs        dd    ?        ; GS
  142.     _Fs        dd    ?        ; FS
  143.     _Ds        dd    ?        ; DS
  144.     _Ss        dd    ?        ; SS
  145.     _Cs        dd    ?        ; CS
  146.     _Es        dd    ?        ; ES
  147.     TSS_Desc    dd    3 dup (?)    ; TSSR
  148.     IDT_Desc    dd    3 dup (?)    ; IDTR
  149.     Gdt_Desc    dd    3 dup (?)    ; GDTR
  150.     Ldt_Desc    dd    3 dup (?)    ; LDTR
  151.     GS_Desc     dd    3 dup (?)    ; GS Desc. Cache
  152.     FS_Desc     dd    3 dup (?)    ; FS Desc. Cache
  153.     DS_Desc     dd    3 dup (?)    ; DS Desc. Cache
  154.     SS_Desc     dd    3 dup (?)    ; SS Desc. Cache
  155.     CS_Desc     dd    3 dup (?)    ; CS Desc. Cache
  156.     ES_Desc     dd    3 dup (?)    ; ES Desc. Cache
  157.             dd    0ah dup (?)    ; RESERVED
  158. Loadall_Struc3    ENDS
  159.  
  160. INT_VEC     STRUC
  161.     int_offset    dw    ?
  162.     int_segment    dw    ?
  163. INT_VEC     ENDS
  164.  
  165.  
  166. ;---------------------------------------------------------------
  167. ; Equate definitions
  168. ;---------------------------------------------------------------
  169.     LOADALL286    equ    050fh
  170.     CRLF        equ    <0dh,0ah>
  171.     CRLF$        equ    <0dh,0ah,'$'>
  172.     INT6        equ    [bp-4]
  173.  
  174.  
  175. ;---------------------------------------------------------------
  176. ; Macro definitions
  177. ;---------------------------------------------------------------
  178.     LOADALL_386    MACRO
  179.         db    0fh,07h
  180.     ENDM
  181.  
  182.  
  183.     PRINT_STRING    MACRO    MSG_NAME
  184.     mov    ah,9
  185.     mov    dx,offset MSG_NAME
  186.     int    21h
  187.     ENDM
  188.  
  189.  
  190.  
  191. _TEXT    SEGMENT PARA PUBLIC 'CODE'
  192.     Assume    CS:_TEXT, DS:_TEXT, ES:_TEXT, SS:_TEXT
  193.     Org    100h
  194.     .386p
  195. ;---------------------------------------------------------------
  196.   Emulate_286_Loadall    Proc    Far
  197. ;---------------------------------------------------------------
  198.     jmp    EMULOAD     ; goto beginning instruction
  199.  
  200. Align 4
  201. ;---------------------------------------------------------------
  202. ; Local Data
  203. ;---------------------------------------------------------------
  204. Loadall_tbl    Loadall_Struc3 <>
  205.  
  206. emuload_msg    db    "80286 LOADALL EMULATOR utility.",CRLF
  207.         db    "Version 1.0 Only for 80386 computers."
  208.         db    CRLF
  209.         db    "Copyright (c) 1991 Robert Collins."
  210.         db    CRLF$
  211. emu_msg_len    equ    $-emuload_msg
  212.  
  213. align 4
  214. ;---------------------------------------------------------------
  215. ; TSR Code begins here as an INT06 replacement.
  216. ;---------------------------------------------------------------
  217. Int06:    push    bp
  218.     mov    bp,sp
  219.     push    si
  220.     push    ds
  221.     lds    si,[bp][2]        ; get CS:IP of bogus
  222.                     ;  opcode
  223.     cmp    word ptr [si],LOADALL286; was it LOADALL?
  224.     jne    @Not_LOADALL        ; nope
  225.     mov    di,0
  226.     mov    ds,di
  227.     mov    di,cs
  228.     mov    es,di
  229.     mov    edi,offset Loadall_tbl
  230.  
  231. Assume    DS:ABS0, ES:_TEXT, SS:NOTHING
  232. ;---------------------------------------------------------------
  233. ; Convert 80286 registers to 80386 counterparts.  The sequencing
  234. ; order follows the 80386 LOADALL table.
  235. ;---------------------------------------------------------------
  236. ; While mapping MSW to CR0, bit5 in CR0 is documented as
  237. ; RESERVED on the '386 DX, and '1' on the '386 SX.  Bit6 is
  238. ; defined as 'NE' (Numeric Exception) on the '486.  If we wanted
  239. ; this code to work on the '486, then we should mask the lower
  240. ; nibble of MSW with CR0.  But the '486 doesn't have LOADALL,
  241. ; so this isn't necesary.  Next consider the Reserved bit5 on
  242. ; the '386 DX.  Since LOADALL completely redefines the CPU
  243. ; state, it is safe to clear this reserved bit instead of
  244. ; masking it with MSW.
  245. ;---------------------------------------------------------------
  246.     mov    eax,cr0         ; MSW    --> CR0
  247.     mov    ax,Loadall_286._286Msw
  248.     mov    Loadall_tbl._CR0,eax
  249.     movzx    eax,Loadall_286._Flags    ; FLAGS --> EFLAGS
  250.     mov    Loadall_tbl._EFLAGS,eax
  251.  
  252. ;---------------------------------------------------------------
  253. ; Hereafter MOVZX isn't needed because the upper 16-bits are
  254. ; guaranteed to be 0.
  255. ;---------------------------------------------------------------
  256.     mov    ax,Loadall_286._286IP    ; IP    --> EIP
  257.     mov    Loadall_tbl._EIP,eax
  258.     mov    ax,Loadall_286._286DI    ; DI    --> EDI
  259.     mov    Loadall_tbl._EDI,eax
  260.     mov    ax,Loadall_286._286SI    ; SI    --> ESI
  261.     mov    Loadall_tbl._ESI,eax
  262.     mov    ax,Loadall_286._286BP    ; BP    --> EBP
  263.     mov    Loadall_tbl._EBP,eax
  264.     mov    ax,Loadall_286._286SP    ; SP    --> ESP
  265.     mov    Loadall_tbl._ESP,eax
  266.     mov    ax,Loadall_286._286BX    ; BX    --> EBX
  267.     mov    Loadall_tbl._EBX,eax
  268.     mov    ax,Loadall_286._286DX    ; DX    --> EDX
  269.     mov    Loadall_tbl._EDX,eax
  270.     mov    ax,Loadall_286._286CX    ; CX    --> ECX
  271.     mov    Loadall_tbl._ECX,eax
  272.     mov    ax,Loadall_286._286AX    ; AX    --> EAX
  273.     mov    Loadall_tbl._EAX,eax
  274.  
  275. ;---------------------------------------------------------------
  276. ; DR6 & DR7 aren't in the '286, so let's use the current values.
  277. ; By keeping the current values, guarantees that any ICE
  278. ; breakpoints, or debug register breakpoints are preserved.
  279. ; (ICE breakpoints use (at least) the upper two of the
  280. ; 'RESERVED' bits in DR7.
  281. ;---------------------------------------------------------------
  282.     mov    eax,dr6         ; Keep DR6
  283.     mov    Loadall_tbl._DR6,eax
  284.     mov    eax,dr7         ; Keep DR7
  285.     mov    Loadall_tbl._DR7,eax
  286.  
  287.     movzx    eax,Loadall_286._286TR    ; TR    --> TR
  288.     mov    Loadall_tbl._TR,eax
  289.     mov    ax,Loadall_286._286LDT    ; LDT    --> LDT
  290.     mov    Loadall_tbl._LDT,eax
  291.  
  292. ;---------------------------------------------------------------
  293. ; FS & GS aren't in the '286, so let's zero them out.
  294. ;---------------------------------------------------------------
  295.     xor    ax,ax
  296.     mov    Loadall_tbl._GS,eax    ; Clear GS
  297.     mov    Loadall_tbl._FS,eax    ; Clear FS
  298.  
  299.     mov    ax,Loadall_286._286DS    ; DS    --> DS
  300.     mov    Loadall_tbl._DS,eax
  301.     mov    ax,Loadall_286._286SS    ; SS    --> SS
  302.     mov    Loadall_tbl._SS,eax
  303.     mov    ax,Loadall_286._286CS    ; CS    --> CS
  304.     mov    Loadall_tbl._CS,eax
  305.     mov    ax,Loadall_286._286ES    ; ES    --> ES
  306.     mov    Loadall_tbl._ES,eax
  307.  
  308. ;-----------------------------------------------------------
  309. ; Convert '286 descriptor cache register entries to '386
  310. ; format.
  311. ;-----------------------------------------------------------
  312.     mov    esi,offset Loadall_286.TSS_Desc286
  313.     mov    edi,offset Loadall_tbl.TSS_Desc
  314.     call    CVT_Desc
  315.     mov    esi,offset Loadall_286.IDT_Desc286
  316.     mov    edi,offset Loadall_tbl.IDT_Desc
  317.     call    CVT_Desc
  318.     mov    esi,offset Loadall_286.GDT_Desc286
  319.     mov    edi,offset Loadall_tbl.GDT_Desc
  320.     call    CVT_Desc
  321.     mov    esi,offset Loadall_286.LDT_Desc286
  322.     mov    edi,offset Loadall_tbl.LDT_Desc
  323.     call    CVT_Desc
  324.  
  325. ;-----------------------------------------------------------
  326. ; Fill in FS & GS descriptor cache entires with 0.
  327. ;-----------------------------------------------------------
  328.     mov    Loadall_tbl.GS_Desc._Type,93h
  329.     mov    Loadall_tbl.GS_Desc._Addr,0
  330.     mov    Loadall_tbl.GS_Desc._Limit,0ffffh
  331.     mov    Loadall_tbl.FS_Desc._Type,93h
  332.     mov    Loadall_tbl.FS_Desc._Addr,0
  333.     mov    Loadall_tbl.FS_Desc._Limit,0ffffh
  334.  
  335. ;-----------------------------------------------------------
  336. ; Convert '286 descriptor cache register entries to '386
  337. ; format.
  338. ;-----------------------------------------------------------
  339.     mov    esi,offset Loadall_286.DS_Desc286
  340.     mov    edi,offset Loadall_tbl.DS_Desc
  341.     call    CVT_Desc
  342.     mov    esi,offset Loadall_286.SS_Desc286
  343.     mov    edi,offset Loadall_tbl.SS_Desc
  344.     call    CVT_Desc
  345.     mov    esi,offset Loadall_286.CS_Desc286
  346.     mov    edi,offset Loadall_tbl.CS_Desc
  347.     call    CVT_Desc
  348.     mov    esi,offset Loadall_286.ES_Desc286
  349.     mov    edi,offset Loadall_tbl.ES_Desc
  350.     call    CVT_Desc
  351.     mov    edi,offset Loadall_tbl
  352.     LOADALL_386
  353.     HLT            ; This instruction never
  354.                 ;  gets executed
  355.  
  356. @Not_LOADALL:
  357.     pop    ds
  358.     pop    si
  359.     pop    bp
  360.  
  361. Orig_int06:
  362.     jmp    far ptr INT_6
  363. Emulate_286_Loadall    endp
  364.  
  365.  
  366. ;---------------------------------------------------------------
  367.   CVT_Desc    proc    near    ; Convert '286 descriptor table
  368. ;                ; cache register format to '386
  369. ;                ; format.
  370. ;---------------------------------------------------------------
  371. ; Input:   DS:ESI = Pointer to '286 descriptor cache entry
  372. ;       DS:EDI = Pointer to '386 descriptor cache entry
  373. ; Output:  None
  374. ; Register(s) modified:  EAX, EBX, ECX
  375. ;---------------------------------------------------------------
  376.     mov    eax,[esi]        ; get 24-bit base &
  377.                     ;  access rights
  378.     mov    ebx,eax         ; make a copy
  379.     movzx    ecx,[esi]._Limit2    ; get 16-bit limit
  380.     rol    eax,8            ; put access in AL
  381.     and    ebx,00ffffffh        ; make 24-bit address
  382.     mov    ES:[edi]._Type,al    ; store Access
  383.     mov    ES:[edi]._Addr,ebx    ; store Address
  384.     mov    ES:[edi]._Limit,ecx    ; store Limit
  385.     ret
  386. CVT_Desc    endp
  387.  
  388. TSR_End label    word
  389. ;---------------------------------------------------------------
  390. ; End of TSR program
  391. ;---------------------------------------------------------------
  392.  
  393.  
  394. ;---------------------------------------------------------------
  395. ; Local DATA used for initialization code only.
  396. ;---------------------------------------------------------------
  397. bogus_msg1    db    "Unrecognized command line argument."
  398.         db     CRLF$
  399. bogus_msg2    db     "Not 80386 computer.",7,CRLF$
  400.  
  401. driver_msg1    db    "Resident driver installed."
  402.         db     CRLF$
  403. driver_msg2    db    "Resident driver already installed."
  404.         db     7,CRLF$
  405. driver_msg3    db    "Resident driver removed from memory."
  406.         db     CRLF$
  407. driver_msg4    db    "Resident driver was not already "
  408.         db    "installed",7,CRLF$
  409. help_msg    db     CRLF
  410.         db    "Syntax:  EMULOAD",CRLF
  411.         db    "         EMULOAD -R (to remove from "
  412.         db    "memory)",CRLF$
  413.  
  414.  
  415. ASSUME    DS:_TEXT
  416. ;---------------------------------------------------------------
  417.   EMULOAD    proc    near    ; Beginning of initialization
  418. ;                ; code as the NON-TSR part of
  419. ;                ; the program.
  420. ;---------------------------------------------------------------
  421.     cld                ; clear direction flag
  422.     Print_String    emuload_msg    ; Print initialization
  423.                     ;  message.
  424.  
  425. ;---------------------------------------------------------------
  426. ; Check CPU type
  427. ;---------------------------------------------------------------
  428.     call    CPU_TYPE    ; Get CPU type
  429.     and    al,0fh        ; mask out CPU sub-type
  430.     cmp    al,3        ; 80386?
  431.     jz    short @F    ; yes
  432.     Print_String    Bogus_msg2    ; Not 80386 computer
  433.     mov    ax,4c06h        ; set function to DOS
  434.     int    21h            ; exit to DOS
  435.  
  436. ;---------------------------------------------------------------
  437. ; Check command line argument
  438. ;---------------------------------------------------------------
  439. @@:    xor    ax,ax            ; clear AX
  440.     mov    si,80h            ; get start of PSP
  441.     lodsb                ; get command line len.
  442.     or    ax,ax            ; Any command line args?
  443.     jz    short Installed?    ; nope
  444.     mov    cx,ax            ; put into counter
  445.     mov    di,si            ;
  446.     mov    al,' '            ; skip past superfluous
  447.     repz    scasb            ;   blank characters
  448.     cmp    byte ptr [di],0dh    ; are we at the end?
  449.     jz    short Installed?    ; yep
  450.     cmp    byte ptr [di-1],'-'    ; check if it's a switch
  451.     jnz    short @F        ; if not, then error
  452.     mov    si,di            ; get pointer
  453.     lodsb                ; get cmd line switch
  454.     cmp    al,'r'            ; remove driver?
  455.     jz    short remove_driver    ; yep
  456.     cmp    al,'R'            ; remove driver?
  457.     jz    short remove_driver    ; go remove driver
  458.     cmp    al,'?'            ; help?
  459.     jnz    short @F        ; nope
  460.     Print_String    help_msg    ; Print help message
  461.     mov    ax,4c04h        ; set return code
  462.     int    21h            ; exit to DOS
  463.  
  464. ;---------------------------------------------------------------
  465. ; Bogus command line argument
  466. ;---------------------------------------------------------------
  467. @@:    Print_String    bogus_msg1    ; Invalid command line
  468.     mov    ax,4c03h        ; set function code
  469.     int    21h            ; exit to DOS
  470.  
  471. ;---------------------------------------------------------------
  472. ; Remove driver from memory
  473. ;---------------------------------------------------------------
  474. remove_driver:
  475.     call    check_installed     ; Driver installed?
  476.     jnz    short @F        ; driver not installed
  477.     mov    bp,sp            ; create stack frame
  478.     push    ds            ; save (DS)
  479.     mov    dx,ABS0         ; get bottom of memory
  480.     mov    ds,dx            ; make segment register
  481.  
  482. ASSUME    DS:ABS0, ES:_TEXT
  483. ;---------------------------------------------------------------
  484. ; Restore original INT6 vector
  485. ;---------------------------------------------------------------
  486. ; We can restore the original INT6 by getting the vector from
  487. ; our current memory resident driver -- not the DS from the
  488. ; code now executing.  The original DS is the same as the code
  489. ; segment for our EMULOAD driver.  Hence we only need to get
  490. ; the original segment value from the memory resident image.
  491. ; And we get this by looking at the segment for INT6!
  492. ;---------------------------------------------------------------
  493.     mov    es,int_6.int_segment        ; Original DS
  494.     mov    ax,es:orig_int06[1].int_offset    ; Original INT6
  495.     mov    bx,es:orig_int06[1].int_segment ;    "      "
  496.     mov    int_6.int_offset,ax        ; Restore orig.
  497.     mov    int_6.int_segment,bx        ;  INT6
  498.  
  499. ;---------------------------------------------------------------
  500. ; Free memory pointed to by ES
  501. ;---------------------------------------------------------------
  502.     mov    ah,49h            ; DOS FREE_MEM function
  503.     int    21h            ; free allocated memory
  504.     mov    ds,[bp-2]        ; get original (DS)
  505.  
  506. ASSUME    DS:_TEXT
  507. ;---------------------------------------------------------------
  508. ; Now split with TSR removed from memory.
  509. ;---------------------------------------------------------------
  510.     Print_String    driver_msg3    ; Driver removed
  511.     mov    ax,4c05h        ; set function to DOS
  512.     int    21h            ; exit to DOS
  513.  
  514. ;---------------------------------------------------------------
  515. ; If EMULOAD was not in memory, then come here and split with
  516. ; the error code.
  517. ;---------------------------------------------------------------
  518. @@:    Print_String    driver_msg4    ; Driver not installed
  519.     mov    ax,4c01h        ; set function to DOS
  520.     int    21h            ; exit to DOS
  521.  
  522. ;---------------------------------------------------------------
  523. ; Check for driver already installed
  524. ;---------------------------------------------------------------
  525. Installed?:
  526.     call    check_installed     ; check if driver is
  527.     jnz    short @F        ;  already installed?
  528.  
  529. ;---------------------------------------------------------------
  530. ; Driver already installed
  531. ;---------------------------------------------------------------
  532.     Print_String    driver_msg2    ; Driver already inst.
  533.     mov    ax,4c02h        ; set function to DOS
  534.     int    21h            ; exit to DOS
  535.  
  536. ;---------------------------------------------------------------
  537. ; Driver not yet installed
  538. ;---------------------------------------------------------------
  539. @@:    Print_String    driver_msg1    ; Driver now installed
  540.  
  541. ;---------------------------------------------------------------
  542. ; Install driver into memory
  543. ;---------------------------------------------------------------
  544.     xor    dx,dx            ; Point to INT. vectors
  545.     mov    ds,dx            ; complete the move
  546. ASSUME    ds:ABS0
  547.  
  548. ;---------------------------------------------------------------
  549. ; Chain to INT6 by replacing and saving the original INT6
  550. ; vector.
  551. ;---------------------------------------------------------------
  552.     mov    ax,int_6.int_offset        ; Orig. offset
  553.     mov    bx,int_6.int_segment        ; Orig. segment
  554.     mov    orig_int06[1].int_offset,ax    ; save old INT6
  555.     mov    orig_int06[1].int_segment,bx    ;  vector.
  556.  
  557. ;---------------------------------------------------------------
  558. ; Now replace the original INT6 vector.
  559. ;---------------------------------------------------------------
  560.     mov    dx,offset cs:int06    ; Get new INT6 vector
  561.     mov    int_6.int_offset,dx    ;  as CS:INT6
  562.     mov    int_6.int_segment,cs    ;
  563.  
  564. ASSUME    DS:_TEXT
  565. ;---------------------------------------------------------------
  566. ; Terminate and Stay Resident
  567. ;---------------------------------------------------------------
  568.     mov    dx,cs            ; make DS=CS
  569.     mov    ds,dx
  570.     mov    es,ds:[2ch]        ; get DOS env. segment
  571.     mov    ah,49h            ; release memory func.
  572.     int    21h            ; release memory
  573.     mov    dx,offset tsr_end    ; get ending address
  574.     shr    dx,4            ; divide by 16
  575.     adc    dx,1            ; check for remainder;
  576.                     ;  add 1
  577.     mov    ax,3100h        ; set return code to DOS
  578.     int    21h
  579. EMULOAD     endp
  580.  
  581.  
  582. ASSUME    ES:ABS0
  583. ;---------------------------------------------------------------
  584. ; Check to see if the EMULOAD driver is installed in memory.
  585. ; It is possible to check if a TSR program is already installed
  586. ; in memory by looking for a semaphore in the memory image.
  587. ; Luckily we can locate the memory image of our TSR by looking
  588. ; at the current INT6 vector.  The INT6 code segment is the
  589. ; segment of the TSR!  So this routine looks in this segment
  590. ; for the inital banner message:
  591. ;
  592. ;   80286 LOADALL EMULATOR utility.
  593. ;   Version 1.0 Only for 80386 computers.
  594. ;   Copyright (c) 1991 Robert Collins.
  595. ;
  596. ; If this message is found, then the TSR is in memory.    If
  597. ; another TSR has chained to the same INT6 vector, this
  598. ; technique will fail to find EMULOAD, as it very well should!
  599. ;---------------------------------------------------------------
  600.   Check_installed    proc    near
  601. ;---------------------------------------------------------------
  602. ; Input:   None
  603. ; Output:  NZ if NOT installed
  604. ;       ZF if ALREADY installed
  605. ; Register(s) modified:  CX, SI, DI
  606. ;---------------------------------------------------------------
  607.     push    es            ; save (ES)
  608.     mov    cx,ABS0         ; get bios data segment
  609.     mov    es,cx            ; put in (ES)
  610.     mov    cx,emu_msg_len        ; # of bytes to compare
  611.     mov    si,offset emuload_msg    ; get address of message
  612.     les    di,ES:INT_6        ; get INT6 vector
  613.     sub    di,int06-emuload_msg    ; point to theoretical
  614.                     ;  start of message
  615.     repz    cmpsb            ; check data
  616.     pop    es            ; restore (ES)
  617.     ret                ; split
  618. Check_installed endp
  619.  
  620.  
  621. ;---------------------------------------------------------------
  622. ; Include the CPU_TYPE procedure & LOADALL test
  623. ;---------------------------------------------------------------
  624.     Include CPU_TYPE.ASM
  625.  
  626. _TEXT    ends
  627.     end    Emulate_286_LOADALL
  628.  
  629. ;---------------------------------------------------------------
  630. ;                END LISTING 3
  631. ;---------------------------------------------------------------
  632.