home *** CD-ROM | disk | FTP | other *** search
/ The Unsorted BBS Collection / thegreatunsorted.tar / thegreatunsorted / programming / misc_programming / dos32.asm < prev    next >
Assembly Source File  |  1993-10-04  |  46KB  |  1,692 lines

  1. COMMENT $
  2.  
  3.                       DOS32           Version 0.1
  4.  
  5.            A  32 bit MSDOS extender for assembly programmers
  6.  
  7.                            supporting
  8.  
  9.               Dos Protected Mode Interrupt Specification
  10.                   and
  11.        System BIOS extended memory copy service (INT 15h AH = 87h)
  12.        for without DPMI.
  13.  
  14.  
  15.  
  16.    Written by Adam Seychell     SEP-1993
  17.  
  18.    email   s921880@minyos.xx.rmit.oz.au
  19.  
  20.  
  21.  
  22. $
  23.  
  24. .386p           ; Enable "REAL"  CPU instuctions.
  25.  
  26. Normal_stack    equ 200h    ; Size of your protected mode stack
  27. V86_stack_size     equ 200h    ; Size of stack for V86 interrupt calls
  28.  
  29. PIC_Base    equ 80h        ; Base interrupt address for the 8259s
  30.  
  31.  
  32. Data_sruct    struc
  33. C_EDI        dd 0
  34. C_ESI        dd 0
  35. C_EBP        dd 0
  36. C_resrved    dd 0
  37. C_EBX        dd 0
  38. C_EDX        dd 0
  39. C_ECX        dd 0
  40. C_EAX        dd 0
  41. C_FLAGS        dw 0
  42. C_ES        dw 0
  43. C_DS        dw 0
  44. C_FS        dw 0
  45. C_GS        dw 0
  46. C_IP        dw 0
  47. C_CS        dw 0
  48. C_SP        dw 0
  49. C_SS        dw 0
  50. ends
  51.  
  52.  
  53. RealData struc
  54. Real_GS        dd 0
  55. Real_FS        dd 0
  56. Real_DS        dd 0
  57. Real_ES        dd 0
  58. Real_SS        dd 0
  59. Real_ESP    dd 0
  60. tmp_Real_intNum    db 0
  61. ends
  62.  
  63. DATA32    SEGMENT PUBLIC 'DATA'    USE32
  64.  
  65. global    CODE32_sel    :word
  66. global    CODE16_sel    :word
  67. global    DATA_sel    :word
  68. global    TheSTACK_sel    :word
  69. global    VIDEO_sel    :word
  70. global    FLAT_DATA_sel    :word
  71. global    FLAT_CODE32_sel    :word
  72. global    XMS_sel        :word
  73. global    BASE_sel    :word
  74. global    PSP_sel        :word
  75. global    xms_usage    :dword
  76. global    xms_base    :dword
  77. global    Base_Segment    :word
  78. global    PSP_segment    :word
  79. ENDS
  80.  
  81.  
  82. global  START32    :near
  83. global    IRQ0    :near
  84. global    IRQ1    :near
  85. global    IRQ2    :near
  86. global    IRQ3    :near
  87. global    IRQ4    :near
  88. global    IRQ5    :near
  89. global    IRQ6    :near
  90. global    IRQ7    :near
  91. global    IRQ8    :near
  92. global    IRQ9     :near
  93. global    IRQ10    :near
  94. global    IRQ11    :near
  95. global    IRQ12    :near
  96. global    IRQ13    :near
  97. global    IRQ14    :near
  98. global    IRQ15    :near
  99.  
  100. DATA32    SEGMENT PUBLIC 'DATA'    USE32
  101.  
  102. DOS_CODE_sel    dw DOS_CODE_Desc - GDT
  103. DOS_DATA_sel    dw DOS_DATA_Desc - GDT
  104.  
  105. tss_Level0ESP    dd 0
  106. V86_Lv0_StkSave    dd 10h dup (0)     ; TSS level 0 ESP save for V86 calls.
  107. IDT_base    dd 0
  108. _tmp0_        dd 0
  109. _tmp1_        dd 0
  110. tmp_Real_Flags    dd 0
  111. V86_irq_Count    db 0
  112.  
  113. DATA32 ENDS
  114.  
  115.  
  116.  
  117. CODE16    SEGMENT PUBLIC 'CODE' USE16
  118. CODE16    ends
  119.  
  120. DATA16    SEGMENT PUBLIC 'DATA' USE16
  121. DATA16    ends
  122.  
  123. CODE32    SEGMENT PUBLIC 'CODE' USE32
  124. assume    DS:DATA32 , CS:CODE32 , es:DATA32
  125.  
  126.  
  127. ;∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·
  128. Setup_Pmode:           ; first 32bit protected mode point
  129.  
  130.  
  131.         sti
  132.     db 0eah            ; jump to start of main program
  133.         dd offset start32 , code32_desc - gdt
  134.  
  135. ;∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·
  136. ;************** EXCEPTION HANDLERS ... *********************
  137. Exception:
  138.     mov    ax,DATA_Desc - GDT
  139.     mov    ds,ax
  140.     mov    es,Flat_data_sel
  141.     mov    ss,TheStack_sel
  142.     mov    fs,FLAT_data_sel
  143.     mov    gs,FLAT_data_sel
  144.     mov    esp,100h
  145.         mov    dx,offset unknown_int_exit_mesg
  146.         mov    ebp,'ERRA'        ; Exit with error code
  147.         int    21h
  148.  
  149. getexeec macro n
  150. _386exception_&n&:
  151.     mov dx,offset e_&n
  152.         jmp All_exceptions
  153. endm
  154. x=0
  155. rept 16
  156. getexeec %x
  157. x=x+1
  158. endm
  159.  
  160. ;═══════════════════════════════════════════════════════════════════════════
  161. All_exceptions:
  162.     mov    esp,100h
  163. ;    jmp _Pmode_exit_error
  164.  
  165. ;∙·∙·∙·∙·∙·∙·∙·∙∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·
  166. _Pmode_exit_error:
  167.     mov    ax,TheSTACK_Desc - GDT
  168.         mov    ss,ax
  169.     mov    ebp,'ERRA'
  170.         int    21h        ; Exit with error
  171.  
  172.  
  173. set1STirqm macro nt
  174. firstIRQ&nt:
  175.         push offset irq&nt
  176.         jmp check_HardwareINT
  177. endm
  178.  
  179. x = 0
  180. rept 16
  181.         set1STirqm %x
  182. x=x+1
  183. endm
  184.  
  185. ;∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·
  186. ;═══════════════════════════════════════════════════════════════════════════
  187. check_HardwareINT proc near
  188.         test dword ptr [esp+3*4],020000h
  189.         jz not_v86_irq                         ; jump if IRQ was from P.mode
  190.  
  191.         push    eax                            ; IRQ was from V86 mode.
  192.         mov    eax,[esp+5*4]         ; Put new V86 stack pointer
  193.         mov    SS:[real_ESP],eax
  194.         mov    eax,[esp+6*4]        ; Put new V86 stack segment
  195.         mov    SS:[real_SS],eax        ; we Don't care about  ES,DS,FS & GS
  196.         pop    eax
  197.  
  198.         mov    fs,[esp+10*4]        ; return segment reg selectors
  199.         mov    ds,[esp+11*4]        ; as they were before entering V86
  200.         mov    gs,[esp+12*4]
  201.         mov    es,[esp+13*4]
  202. not_v86_irq:
  203.     ret                ; Go to IRQ handler
  204. endp
  205.  
  206.  
  207.  
  208. ;∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·
  209. ;═══════════════════════════════════════════════════════════════════════════
  210. ;------- The General Exception Handler ---------------
  211. ;═══════════════════════════════════════════════════════════════════════════
  212. General_Exeption_Handler:
  213.  
  214.         test dword ptr [esp+4*3],0020000h    ;    Test VM bit
  215.     jnz V86_Monitor
  216.         mov dx,offset e_13
  217.         jmp All_Exceptions
  218.  
  219.  
  220.  
  221.      ;*****************************************
  222. ;*********  Virtual 8086 exception handler *********
  223.      ;*****************************************
  224. V86_Monitor proc
  225.         add    esp,4    ; delete the undocumented pushed error code
  226.         pushad
  227.     mov    ax,Flat_DATA_Desc - GDT
  228.         mov    fs,ax
  229.  
  230.      ;;; Find what instruction caused the exception ;;;;
  231.     movzx ebx,word ptr [esp+36]    ; Get CS from stack
  232.     shl ebx,4
  233.     add ebx,[esp+32]        ; Get EIP form stack
  234.     inc dword ptr [esp+32]
  235.     mov dl,fs:[ebx]            ; Get opcode
  236.     mov al,3
  237.     cmp dl,0cch            ; see if INT 3 Breakpoint
  238.     je short DO_v86int        ; if so do it's int
  239.         mov al,4
  240.     cmp dl,0ceh            ; See if INTO
  241.     je short Do_v86int        ; if so do it's int
  242.     cmp dl,0cdh            ; see if INT n
  243.     jne V86exc            ; if not then exception
  244.     inc dword ptr [esp+32]        ; It must be a INT n instruction
  245.     mov al,fs:[ebx+1]        ; get INT n number
  246.  
  247.     cmp al,0FFh            ; If int 0ffh and Then
  248.     jz Exit_V86            ; return to main Program
  249.  
  250.         cmp al,15h
  251.         jnz NoXmsToCopy
  252.  
  253.     cmp byte ptr ss:[esp+7*4+1],87h        ; Detect if v86 application
  254.         jz Emulate_XMS_COPY            ; wants to copy extended mem
  255.                                                 ; i.e ah = 87h
  256.  
  257. NoXmsToCopy:
  258.  
  259.  ;****; Emulate V86 interrupt ;****;
  260. DO_v86int:                ; Do interrupt "AL" for V86 task
  261.     movzx ebx,al
  262.     shl ebx,2            ; Get 8086 Int Vector
  263.         movzx edx,word ptr [esp+(8+4)*4]    ; Get SS stored on stack
  264.         shl edx,4
  265.         sub word ptr [esp+(8+3)*4],6        ; Sub ESP stored on stack by 6
  266.         add edx,[esp+(8+3)*4]        ; edx = Phyical Address of V86 stack
  267.     mov ax,[esp+(8+2)*4]    ;Put FLAGS from Prev.0 Stack to V86 stack
  268.     mov fs:[edx+4],ax
  269.     mov ax,[esp+(8+1)*4]        ;Put CS from Prev.0 Stack to V86 stack
  270.     mov fs:[edx+2],ax
  271.     mov ax,[esp+(8+0)*4]        ;Put IP from Prev.0 Stack to V86 stack
  272.     mov fs:[edx],ax
  273.     mov eax,fs:[ebx]        ; Get real mode int vector (CS:IP)
  274.     mov [esp+(8+0)*4],ax        ; Store it on prev. 0 Stack
  275.     shr eax,16
  276.     mov [esp+(8+1)*4],ax
  277. ret86:    and word ptr [esp+(8+2)*4],0fcffh
  278.         popad            ; Clear DF & IF flags on prev. 0 Stack
  279.         iretd                           ; Return to V86 mode
  280.  
  281. ;∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·
  282. Exit_V86:
  283.     mov    ax,DATA_Desc - GDT
  284.     mov    ds,ax
  285.         popad
  286.         mov    [_tmp0_],eax
  287.         mov    [_tmp1_],ebx
  288.  
  289.         add    esp,8                ; ignore EIP & CS
  290.         pop    word ptr [esp+12*4+2]           ; Get V86 EFLAGS onto
  291.         add    esp,2                ;  stack from the int 20h
  292.         pop    ss:[Real_ESP]
  293.         pop    ss:[Real_SS]
  294.     pop    ss:[Real_ES]
  295.     pop    ss:[Real_DS]
  296.     pop    ss:[Real_FS]
  297.     pop    ss:[Real_GS]
  298.  
  299.  
  300. ;Must return the TSS Level 0 ESP to the previous V86 call's Level 0 ESP value.
  301.         movzx    eax,V86_irq_Count
  302.         sub    al,1
  303.         jle   jH98_V86        ; Only do it if a V86 call inside a call.
  304.        dec    V86_irq_Count
  305.       dec    eax                
  306.           mov    eax,[V86_Lv0_StkSave+EAX*4]     ; Get previous TSS Lv0 ESP
  307.           mov    ebx,[tss_Level0ESP]             ; Get address of TSS Lv0 ESP
  308.           mov    fs:[ebx],eax                 ; Load it.
  309. jH98_V86:
  310.  
  311.         mov    eax,[_tmp0_]        ;Return temperaly saved registers
  312.         mov    ebx,[_tmp1_]
  313.  
  314.     pop     fs ds         ; pop seg reg from the entering V86
  315.     pop    gs es        ; call; see  My_EmulateRealInterupt proc
  316.  
  317.         iretd            ; Return to main program
  318.  
  319.  
  320. ;∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·
  321. ;═══════════════════════════════════════════════════════════════════════════
  322. ; Emulate the SYSTEM BIOS - COPY EXTENDED MEMORY Srevice for V86 application
  323. ; INT 15  & AH = 87h
  324. ;═══════════════════════════════════════════════════════════════════════════
  325.  
  326. COMMENT $
  327.  
  328. NOTE.
  329.   There is a problem with the BIOS int 15h ah = 87 emulation
  330.   when HIMEM.SYS calls it to transfer a XMS block while MSDOS is loaded
  331.   in the Upper Memeory Block. It seems to be called with the location
  332.   of the GDT ( for int 15 ah=87 ) in the ROM area. This gives an invalid GDT.
  333.  When DOS is loaded into convention memory everything work fine because
  334.   HIMEM.SYS returns a valid GDT on this call.
  335. $
  336.  
  337. Emulate_XMS_COPY:        ; A20 gate always seems to be on ?
  338. ;    mov    ax,DATA_Desc - GDT
  339. ;    mov    ds,ax
  340.  
  341.     mov    ecx,ss:[esp+(6)*4]    ; Get Number of words to copy
  342.         and    ecx,0ffffh
  343.     cmp    cx,8000h
  344.         ja _error_1587
  345.     shr    ecx,1
  346.  
  347.         xor    eax,eax
  348.         mov    ax,ss:[esp+(8+5)*4]        ; Get ES
  349.         shl    eax,4
  350.         add     ax,ss:[esp+(1)*4]        ; Get SI
  351.         adc    eax,0            ; EAX has location of GDT
  352.         mov    ebx,eax
  353. ;         sub    ebx,0f0000h
  354. ;         cmp    ebx,010000h
  355. ;         ja _error_1587
  356. ;        push    eax
  357.         mov     esi,fs:[eax+7h+10h]
  358.         shl     esi,24
  359.         mov    edx,fs:[eax+2h+10h]    ; Get 32bit Source address
  360.         and    edx,0ffffffh
  361.         add     esi,edx
  362.  
  363.         mov     edi,fs:[eax+7h+18h]
  364.         shl     edi,24
  365.         mov    edx,fs:[eax+2h+18h]    ; Get 32bit Destination address
  366.         and    edx,0ffffffh
  367.         add     edi,edx
  368.  
  369.  
  370. ;       write 'Source ',12
  371. ;        mov edx,esi
  372. ;        call hex_dword
  373.  
  374. ;        write ' Destination ',12
  375. ;        mov edx,edi
  376. ;        call hex_dword
  377.  
  378. ;        write ' Cout ',12
  379. ;        mov edx,ecx
  380. ;        shl edx,2
  381. ;        call hex_dword
  382.  
  383. ;        write ' GDT ',12
  384. ;        pop    edx
  385. ;        call hex_dword
  386.  
  387. ;        write ' CS:EIP ',10
  388. ;    movzx edx,word ptr [esp+36]    ; Get CS from stack
  389. ;    shl edx,4
  390. ;    add edx,[esp+32]        ; Get EIP form stack
  391. ;        call hex_dword
  392. ;
  393. ;        write 'int 15 vect',11
  394. ;    movzx edx,word ptr fs:[15h*4+2]
  395. ;    shl edx,4
  396. ;    add dx,fs:[15h*4]
  397. ;        adc edx,0
  398. ;        call hex_dword
  399. ;        writeln
  400.  
  401.     push fs
  402.         pop es
  403.     cld
  404.         rep    movs dword ptr es:[edi],es:[esi]    ; do the transfer
  405.  
  406.         mov    byte ptr [esp+(7*4)+1],00        ;return AH = 0
  407.  
  408.     and    byte ptr [esp+(8+2)*4],NOT 01    ; Clear Carry  flag on prev. 0 Stack
  409.  
  410.         jmp ret86
  411.  
  412. _error_1587:
  413.     or byte ptr [esp+(8+2)*4],01    ; Set Carry  flag on prev. 0 Stack
  414.         mov    byte ptr [esp+(7*4)+1],03        ;return AH
  415.     jmp ret86
  416. ;∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·
  417.  
  418.  
  419. ;∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·
  420. ;═══════════════════════════════════════════════════════════════════════════
  421. V86exc:
  422.         mov    dx,offset _V86_illigal_err
  423.         jmp    _Pmode_exit_error
  424.  
  425. ;∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·
  426.  
  427. ;¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡
  428.  
  429.  
  430. endp
  431.  
  432.  
  433.  
  434. ;**********************************
  435. MyDPMI_services:;*********************
  436. ;**********************************
  437.         cmp    ax,0205h
  438.         jz SetPmodeintVector
  439.         cmp    ax,0204h
  440.         jz GetPmodeintVector
  441.         cmp    ax,0400h
  442.         jz GetVersion
  443.             iretd
  444.  
  445. SetPmodeintVector:
  446.            push edi ebx fs ds
  447.        mov  ax,data_desc - gdt
  448.            mov  ds,ax
  449.            mov fs,[flat_DATA_sel]
  450.            movzx ebx,bl
  451.            mov edi,ebx
  452.            sub    edi,Pic_Base    ; No allowed to set the hardware int vectors
  453.            cmp    edi,15
  454.            jbe Set_irq_vec
  455.        mov    edi,[idt_base]
  456.            mov    fs:[ebx*8+edi],dx    ; offset 0..15
  457.            SHR    EDX,16
  458.            mov    fs:[ebx*8+edi+6],dx    ; offset 16..32
  459.            mov    fs:[ebx*8+edi+2],cx    ; Code Selector
  460.        pop ds fs ebx edi
  461.          iretd
  462.  
  463. GetPmodeintVector:
  464.            push edi ebx fs ds
  465.        mov  ax,data_desc - gdt
  466.            mov  ds,ax
  467.            mov fs,[flat_DATA_sel]
  468.            movzx ebx,bl
  469.            shl    ebx,3
  470.            add    ebx,[idt_base]
  471.        mov    edi,[idt_base]
  472.            mov    dx,fs:[ebx+6]        ; Get offset 16..32
  473.            SHL    EDX,16
  474.            mov    dx,fs:[ebx]        ; Get offset 0..15
  475.            mov    cx,fs:[ebx+2]        ; Get Code Selector
  476. ivec22:       pop ds fs ebx edi
  477.        iretd
  478.  
  479. Set_irq_vec:
  480.     stc
  481.     jmp ivec22
  482.  
  483.  
  484. GetVersion:    ; Emulate DPMI service Get Version
  485.         ; only need to emulate the returned values of PIC bases
  486.     mov dh,PIC_base
  487.     mov dl,PIC_base+8
  488.     iretd
  489.  
  490. ;═══════════════════════════════════════════════════════════════════════════
  491. ;        PROCEDURE TO EMULATE REAL MODE INTERRUPT
  492. ;
  493. ;═══════════════════════════════════════════════════════════════════════════
  494. DPMI_EmulateRealInterupt proc far
  495.     push    ax
  496.     push  0 0 0
  497.     push    word ptr ss:[Real_DS]
  498.         push    word ptr ss:[Real_ES]
  499.         push    word ptr [esp+18+8]
  500.         pushad
  501.     mov    edi,esp
  502.         push es
  503.     push ss
  504.         pop es
  505.         mov    ax,0300h
  506.         mov    bl,ss:[tmp_Real_intNum]
  507.         xor    ecx,ecx
  508.         int    31h                 ; Use the DPMI service
  509.         pop es
  510.         popad
  511.         pop    word ptr [esp+26]        ; return eflags
  512.         pop    word ptr ss:[Real_ES]
  513.         pop    word ptr ss:[Real_DS]
  514.         add    esp,14
  515.         iretd
  516. ENDP
  517.  
  518.  
  519. ;∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·
  520. My_EmulateRealInterupt proc far
  521.  
  522.     push    es gs ds fs        ; save segment registers.
  523.         push eax
  524.  
  525.         mov    ax,data_desc  - gdt    ; Load seg regs.
  526.         mov    ds,ax
  527.     mov    fs,[flat_data_sel]
  528.  
  529.         pop    _tmp0_            ; temperly save  eax.
  530.  
  531.         mov    eax,[esp+4*6]        ; Get flags from stack.
  532.         mov     [tmp_Real_Flags],eax    ; Temperaly saved them.
  533.  
  534.     mov    eax,[tss_Level0esp]    ; Set Level 0 stack to current ESP
  535.         mov    fs:[eax],esp
  536.  
  537.         movzx    eax,V86_irq_Count
  538.         mov    [V86_Lv0_StkSave+EAX*4], ESP
  539.     inc    V86_irq_Count
  540.  
  541.         pushfd                ; Clear Nested Task, ( bit 14 )
  542.         pop eax                ; If set then the 386 will
  543.         and ah,10111111b        ; use the back link field in the TSS
  544.         push eax            ; to switch tasks. A no no.
  545.         popfd
  546.  
  547.         mov    eax,seg V86IntNumber
  548.         shl    eax,4
  549.  
  550.         push ebx            ; Load the V86 interrupt number
  551.         mov bl,SS:[tmp_Real_intNum]            ; get it
  552.     mov byte ptr fs:[offset V86IntNumber+1+EAX],BL    ; put it
  553.         pop ebx
  554.     push    SS:[Real_GS]            ; GS
  555.     push    SS:[Real_FS]            ; FS
  556.     push    SS:[Real_DS]            ; DS
  557.     push    SS:[Real_ES]            ; ES
  558.     push    SS:[Real_SS]            ; SS
  559.     push    SS:[Real_ESP]            ; ESP
  560.     mov    eax,00023000h               ; IOPL = 3 , VM = 1
  561.         or    ax,word ptr [tmp_Real_Flags]
  562.     push    eax                ; EFLAGS
  563.     mov    eax,seg TASK0_V86
  564.     push    eax                ; CS
  565.     mov    eax,offset TASK0_V86
  566.     push    eax                ; EIP
  567.         mov    eax,_tmp0_            ; Return origonal EAX value
  568.     IRETD                ; Enter V86 mode !!!!!
  569. endp
  570. ;¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡
  571.  
  572. TASK0_V86:
  573.  
  574. V86IntNumber:      int 000h
  575.             int 0ffh    ; exit V86 mode
  576.  
  577. CODE32 ENDS
  578.  
  579.  
  580.  
  581.  
  582.  
  583.  
  584.  
  585.  
  586.  
  587. DOS_CODE    SEGMENT PUBLIC 'CODE' USE16
  588. assume CS:dos_CODE , DS:DOS_CODE , fs:data32
  589.  
  590. ;
  591. ; Format of a 386DX TSS (Task State Segment)
  592. ;
  593. tss        struc
  594. tss_prev    dw    0    ,0        ; back link to previous TSS
  595. tss_esp0    dd    0            ; Priv. 0 ESP
  596. tss_ss0        dw    0            ; Priv. 0 SS
  597.         dw    0            ; unused
  598. tss_esp1    dd    0            ; Priv. 1 ESP
  599. tss_ss1        dw    0            ; Priv. 1 SS
  600.         dw    0            ; unused
  601. tss_esp2    dd    0            ; Priv. 2 ESP
  602. tss_ss2        dw    0            ; Priv. 2 SS
  603.         dw    0            ; unused
  604. tss_cr3        dd    0            ; PDBR
  605. tss_eip        dd    0
  606. tss_eflags    dd    0
  607. tss_eax        dd    0
  608. tss_ecx        dd    0
  609. tss_edx        dd    0
  610. tss_ebx        dd    0
  611. tss_esp        dd    0
  612. tss_ebp        dd    0
  613. tss_esi        dd    0
  614. tss_edi        dd    0
  615. tss_es        dw    0,0
  616. tss_cs        dw    0,0
  617. tss_ss        dw    0,0
  618. tss_ds        dw    0,0
  619. tss_fs        dw    0,0
  620. tss_gs        dw    0,0
  621. tss_ldt        dw    0,0
  622. tss_t        dw    0        ; if bit 0 set, exception on tsk switch
  623. tss_iobase    dw    068h        ; points to beg. of I/O permissions map
  624. tss_iomap    db    2000h dup (0)    ; I/O permissions bit map
  625. tss_ioend    db    11111111b    ; I/O map trailer
  626. TSS_ENDS    equ    $
  627. tss        ends
  628.  
  629.  
  630. s_ACCESS record d_P:1,d_DPL:2,s_S:1,d_TYPE:4
  631. s_INFO   record d_G:1,d_D:1,d_nul:1,d_avl:1,d_lim:4
  632.  
  633. align 8
  634. GDT        dd 0,0          ; First descriptor is always NULL.
  635.  
  636. ;    Data DESCRIPTOR for a FLAT memory model
  637. Flat_Data_Desc    dw 0ffffh             ; Limit[15..0]
  638.         db 0,0,0            ; Base[23..0]
  639.          s_ACCESS <1,00b,1,0010b>    ; P,DPL,1,type[E=0,ED,W,A ]
  640.         s_INFO <1,1,0,0,0fh>        ; G,B,0,avl,Limit[19..16]
  641.             db 0                ; Base[31..24]
  642.  
  643. ;    Code DESCRIPTOR for a FLAT memory model
  644. Flat_Code32_Desc dw 0ffffh             ; Limit[15..0]
  645.          db 0,0,0            ; Base[23..0]
  646.          s_ACCESS <1,00,1,1010b>    ; P,DPL,1,type[E=1,C,R,A ]
  647.          s_INFO <1,1,0,0,0fh>        ; G,D,0,avl,Limit[19..16]
  648.          db 0                ; Base[31..24]
  649.  
  650. ;    Data DESCRIPTOR for the free extented memory block
  651. XMS_Desc    dw 0000h             ; Limit[15..0]
  652.         db 00,00,10h            ; Base[23..0]
  653.          s_ACCESS <1,00b,1,0010b>    ; P,DPL,1,type[E=0,ED,W,A ]
  654.         s_INFO <1,0,0,0,00h>        ; G,B,0,avl,Limit[19..16]
  655.             db 0                ; Base[31..24]
  656.  
  657. ;    Data DESCRIPTOR with base = start of free base memory
  658. BASE_Desc    dw 0ffffh             ; Limit[15..0]
  659.         db ?,?,?            ; Base[23..0]
  660.          s_ACCESS <1,00,1,0010b>        ; P,DPL,1,type[E=0,ED,W,A ]
  661.         s_INFO <0,0,0,0,0fh>        ; G,B,0,avl,Limit[19..16]
  662.             db 0                ; Base[31..24]
  663.  
  664. ;    Data DESCRIPTOR     with base = 0A0000h
  665. Video_Desc    dw 0ffffh             ; Limit[15..0]
  666.         db 00,00,0Ah            ; Base[23..0]
  667.          s_ACCESS <1,00,1,0010b>        ; P,DPL,1,type[E=0,ED,W,A ]
  668.         s_INFO <0,0,0,0,01h>        ; G,B,0,avl,Limit[19..16]
  669.             db 0                ; Base[31..24]
  670.  
  671.  
  672. ;    Data DESCRIPTOR     for the STACK
  673. TheSTACK_Desc    dw Normal_stack-1         ; Limit[15..0]
  674.         db 00,00,00h            ; Base[23..0]
  675.          s_ACCESS <1,00,1,0010b>        ; P,DPL,1,type[E=0,ED,W,A ]
  676.         s_INFO <0,1,0,0,00h>        ; G,B,0,avl,Limit[19..16]
  677.             db 0                ; Base[31..24]
  678.  
  679. ;    16bit data and code DESCRIPTORS for real mode ( DOS )
  680. DOS_Code_Desc    dw 0ffffh            ; Limit[15..0]
  681.         db ?,?,?            ; Base[23..0]
  682.          s_ACCESS <1,00,1,1010b>        ; P,DPL,1,type[E=1,C,R,A ]
  683.         s_INFO <0,0,0,0,00h>        ; G,D,0,avl,Limit[19..16]
  684.             db 0                ; Base[31..24]
  685.  
  686. Dos_Data_Desc    dw 0ffffh             ; Limit[15..0]
  687.         db ?,?,?            ; Base[23..0]
  688.          s_ACCESS <1,00,1,0010b>        ; P,DPL,1,type[E=0,ED,W,A ]
  689.         s_INFO <0,0,0,0,0h>        ; G,B,0,avl,Limit[19..16]
  690.             db 0                ; Base[31..24]
  691.  
  692.  
  693. ;    Data PSP Descr   with base = PSP , limit = 100h
  694. PSP_desc    dw 0ffh                 ; Limit[15..0]
  695.         db 00,00,00h            ; Base[23..0]
  696.          s_ACCESS <1,00,1,0010b>        ; P,DPL,1,type[E=0,ED,W,A ]
  697.         s_INFO <0,0,0,0,00h>        ; G,B,0,avl,Limit[19..16]
  698.             db 0                ; Base[31..24]
  699.  
  700. ;    DATA and CODE  DESCRIPTORS for your dos extender
  701.  
  702. Code32_Desc    dw 0ffffh            ; Limit[15..0]
  703.         db ?,?,?            ; Base[23..0]
  704.          s_ACCESS <1,00,1,1010b>        ; P,DPL,1,type[E=1,C,R,A ]
  705.         s_INFO <0,1,0,0,0fh>        ; G,D,0,avl,Limit[19..16]
  706.             db 0                ; Base[31..24]
  707.  
  708. Code16_Desc    dw 0ffffh            ; Limit[15..0]
  709.         db ?,?,?            ; Base[23..0]
  710.          s_ACCESS <1,00,1,1010b>        ; P,DPL,1,type[E=1,C,R,A ]
  711.         s_INFO <0,0,0,0,0fh>        ; G,D,0,avl,Limit[19..16]
  712.             db 0                ; Base[31..24]
  713.  
  714.  
  715. Data_Desc    dw 0ffffh             ; Limit[15..0]
  716.         db ?,?,?            ; Base[23..0]
  717.          s_ACCESS <1,00b,1,0010b>    ; P,DPL,1,type[E=0,ED,W,A ]
  718.         s_INFO <0,0,0,0,0fh>        ; G,B,0,avl,Limit[19..16]
  719.             db 0                ; Base[31..24]
  720.  
  721.  
  722. MyMain_TSS_Desc    dw TSS_ends            ; Limit[15..0]
  723.         db ?,?,?            ; Base[23..0]
  724.         s_ACCESS <1,00,0,09h>        ; P,DPL,0,(type  = avalible 386 TSS )
  725.         s_INFO <0,0,0,0,00h>        ; G,0,0,0,Limit[19..16]
  726.         db 0                ; Base[31..24]
  727.  
  728.  
  729. GDT_ends    equ    $ - GDT
  730.  
  731.  
  732. ;======== ERROR MESSAGES FOR PROGRAM TERMINATION IN NON-DPMI ===============
  733. unknown_int_exit_mesg db 'Exited from Unhandled protected mode interrupt',10,13,36
  734. _V86_illigal_err db 10,13,' Invalid Instuction in V86 mode ',10,13,36
  735. _exit_errror    db 10,10,' PROGRAM TERMINATED ',10,13,7,36
  736. e_0 db '0  Divide error',10,13,36
  737. e_1 db '1  Debug exception',10,13,36
  738. e_2 db '2  Non-Maskable interrupt',10,13,36
  739. e_3 db '3  Breakpoint',10,13,36
  740. e_4 db '4  Overflow',10,13,36
  741. e_5 db '5  Range Exceeded',10,13,36
  742. e_6 db '6  Invalid opcode',10,13,36
  743. e_7 db '7  No math unit avalible',10,13,36
  744. e_8 db '8  Reserved',10,13,36
  745. e_9 db '9  Reserved',10,13,36
  746. e_10 db '10  Invalid TSS',10,13,36
  747. e_11 db '11 Segment Not Present',10,13,36
  748. e_12 db '12  Stack exception',10,13,36
  749. e_13 db '13 General Protection Exception',10,13,36
  750. e_14 db '14  Page fault',10,13,36
  751. e_15 db '14  Reserved',10,13,36
  752.  
  753. DOS_IDT_value    dw 03ffh,0,0,0
  754.  
  755. DPMI_entry    dw 0,0
  756. xms_usage_tmp    dd 0
  757. _tmpL_xms_base    dw 0
  758. _tmpH_xms_base    dw 0
  759. xms_driver    dd 0
  760. XMS_handle    dw 0,0
  761. oirqMask    db 0,0
  762. DPMI_Selector    dw 0
  763. PIC1_Base    db 0
  764. PIC2_Base    db 0
  765.  
  766. ;----------------------------------------------------------------------------
  767. ;─────────────────────  INTERNAL ROUTINES ───────────────────────────────────
  768. ;----------------------------------------------------------------------------
  769.  
  770. ;∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·
  771. ;∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·
  772. free_XMS_memory proc near
  773.             cmp [xms_driver],0
  774.             jz No_xms_driver
  775.  
  776.  
  777.                 ; UNLOCK THE ALLOCATED EXTENDED MEMORY BLOCK
  778.         mov    ah,0Dh
  779.                 mov    dx,[XMS_handle]
  780.                 call    [XMS_Driver]
  781.  
  782.         ; FREE ALLOCATED BLOCK
  783.                 MOV    AH,0Ah
  784.         mov    dx,[XMS_handle]
  785.                 call    [xms_driver]
  786. No_xms_driver:    RET
  787.  
  788. free_XMS_memory    endp
  789. ;∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·
  790. ;─────────────────────────────────────────────────────────────────────────────
  791.             ; Set new IRQ vector numbers
  792. set_8259intvec  proc    ; Set IRQ vectors 0..7 to bl
  793.             ; and  IRQ vectors 8..15 to bh
  794.  
  795.         CLI              ;∙·∙·∙·∙·∙·∙·  set first 8259A PIC  ∙·∙·∙·∙·∙·∙·
  796.  
  797.         mov al,00010001b    ;ICW1
  798.         out 20h,al          ;icw4 is needed
  799.         call Delay8259
  800.         mov al,bl       ;ICW2
  801.         out 21h,al      ;( Set PIC 1 Base interrupt number )
  802.         call Delay8259
  803.         mov al,4h       ;ICW3
  804.         out 21h,al
  805.         call Delay8259
  806.         mov al,1h       ;ICW4
  807.         out 21h,al
  808.         call Delay8259  ;∙·∙·∙·∙·∙·∙·  set second 8259A PIC  ∙·∙·∙·∙·∙·∙·
  809.         mov al,00010001b    ;ICW1
  810.         out 0a0h,al     ;icw4 is needed
  811.         call Delay8259
  812.         mov al,bh       ;ICW2
  813.         out 0a1h,al     ;( Set PIC 2 Base interrupt number )
  814.         call Delay8259
  815.         mov al,00000010b    ;ICW3
  816.         out 0a1h,al
  817.         call Delay8259
  818.         mov al,0000001b     ;ICW4
  819.         out 0a1h,al
  820.         call Delay8259
  821.         ret
  822.  
  823. delay8259:  mov ax,1000h
  824.     @3del:  dec ax
  825.             jnz @3del
  826.             ret
  827. ;∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·
  828. ;─────────────────────────────────────────────────────────────────────────────
  829. endp
  830.  
  831.  
  832.  
  833. Go_REAL_MODE proc near
  834.  
  835. ;─────────────────────────────────────────────────────────────────────────────
  836. ; Entry point to exit proteceded mode and restore hardware configeration.
  837. ; Then exits back to MSDOS. ( only for non-DPMI )
  838. ;─────────────────────────────────────────────────────────────────────────────
  839.     cli
  840.  
  841.     mov al,00110100b    ; SLOW DOWN TIMER
  842.     out 43h,al
  843.         XOR AL,AL
  844.     out 40h,al
  845.     out 40h,al
  846.  
  847. ; Exit protected mode and return to DOS
  848.  
  849. ; Load Data registers with 8086 SEGMENTs
  850.         mov    ax,DOS_Data_Desc - GDT
  851.         mov    ss,ax
  852.         mov    es,ax
  853.         mov    ds,ax
  854.         mov    fs,ax
  855.         mov    gs,ax
  856.  
  857.  
  858.         cli
  859.         lidt    qword ptr DOS_IDT_value        ; Set IDT to how DOS want's it
  860.  
  861. ; Exit protecded mode
  862.         mov    eax,CR0
  863.         and    al,NOT 1        ;Clear PE bit
  864.         mov    CR0,eax
  865.  
  866.         db 0eah
  867.         dw  To_MSDOS , Dos_CODE    ; reload CS:IP
  868.  
  869. To_MSDOS:        ;-- remap IRQ int vectors ---
  870.         mov    bl,008h
  871.             mov    bh,070h
  872.         call    set_8259intvec
  873.  
  874.  
  875. assume ds:dos_code
  876.         mov ax,dos_code
  877.         mov ds,ax
  878.         mov ax,TheStack        ; Set up a bit of stack just to exit
  879.         mov ss,ax
  880.         mov esp,100h
  881.  
  882.         mov al,oirqMask         ; return origonal values of the IRQ mask bits
  883.         out 21h,al
  884.         mov al,oirqMask+1
  885.         out 0A1h,al
  886.  
  887.  
  888.         mov al,20h
  889.         out 20h,al
  890.         out 0a0h,al
  891.  
  892.         in al,60h
  893.  
  894.         cmp    ebp,'ERRA'
  895.         jnz normal_terminate
  896.             ; Print error message if need to
  897.                 mov    ah,9
  898.                 int    21h
  899.                 mov    dx,offset _exit_errror
  900.                 int    21h
  901.  
  902. normal_terminate:
  903.  
  904.     call free_XMS_memory        ; deallocated XMS
  905.  
  906. Exit_To_MSDOS:
  907.      mov    ax,4C00h
  908.         int    21h
  909. assume ds:dos_code
  910.  
  911. endp
  912.  
  913. ;---------------- finished exiting routine -------------------------
  914.  
  915. COMMENT $
  916.  
  917.  All data below this point of this segment is not needed after initalization.
  918.  Thus it can be (next Version) over witten after all the setting up is done.
  919.   This saves a bytes.  See the 32bit setup code at "Setup_Pmode:" above.
  920.  
  921.   >->->->->->->->->->->->->->->->->->->->->->->->->->->->->->->->->->->->->->
  922. $
  923.  
  924. align 16
  925. NON_DPMI_initalize_start:
  926.  
  927.  
  928. GDTR_value    dw    GDT_ends - 1
  929.         dd   offset GDT
  930. IDTR_value    dq 0000000007ffh
  931.  
  932. Label InterruptGATE_a dword
  933.           dw offset exception        ; Offset[15..0]
  934.     dw Code32_Desc - GDT        ; Selector
  935. Label InterruptGATE_b dword
  936.         db 00000000b            ; 0,0,0,WordCnt[4..0]
  937.      s_ACCESS <1,00b,0,0Eh>        ; P,DPL,0,type = 386 interrupt Gate
  938.            dw 0                ; Offset[31..16]
  939.  
  940.  
  941. ;═════════════════ INITALIZATION ERROR MESSAGES ════════════════════════════
  942. _inV86_err db '  Unable to enter protected mode because another protected mode ',10,13
  943. db 'application is operating and does not support Dos Protected Mode Interface',10,13
  944. db 'specifiaction.',10,13,10
  945. db ' Disable the protected mode sofware and try again.',10,13,36
  946. mesg_TimeOut8042 db 'Time out error in the keyboard controller (8042) failing to ',10,13,' respond on enabling the A20 gate.',10,13
  947. all_DPMI_err    db 'Encountered DPMI error: ',36
  948. pmiERr        db 'Switching to protecded mode.',10,13,36
  949. No_Mem_err    db 'Not Enough Base memory.  6000 bytes needed.',10,13,36
  950. erralc_mesg    db 'Can''t allocate descriptors.',10,13,36
  951. errset_mesg    db 'Can''t Set descriptors.',10,13,36
  952. dpmi_aloc_err    db 'Can''t allocate extended memory.',10,13,36
  953. dpmi_lock_err    db 'Unable to lock allocated memory.',10,13,36
  954. dpmi_free_err    db 'Unable to get free memory information.',10,13,36
  955. mesgA20_err     db 'ERROR:  Physical A20 gate test failed.',10,13,36
  956. xms_mesgA20_err    db 'ERROR:  XMS enabling the A20 gate.',10,13,36
  957. xms_vers_err    db 'Need XMS v3.0 or greater.',10,13,36
  958. xms_alloc_Err    db 'Can''t allocate XMS memory.',10,13,36
  959. xms_lock_err    db 'Can''t lock allocated XMS memory.',10,13,36
  960.  
  961. CALL_DATA    Data_sruct <>
  962.  
  963.  
  964. DosStart proc
  965.         mov    ax,DATA32
  966.         mov    fs,ax
  967.         mov    fs:[psp_segment],DS        ; store psp_segment
  968.  
  969.     mov    ax,DOS_CODE
  970.         mov    ds,ax
  971.  
  972.          ; Get end of program address segment
  973.     mov    bx,SP
  974.     shr    bx,4
  975.     inc     bx
  976.     mov    ax,SS
  977.     add    bx,ax
  978.     mov    FS:Base_Segment,bx
  979.  
  980.  
  981.  
  982. ; SET GLOBAL DISCRIPTOR TABLE Base Values ( USEING THE MACRO )
  983.  
  984. Fix_Desc_BASE Macro  Descriptor,RealSeg
  985.         xor eax,eax
  986.     mov ax,RealSeg
  987.         shl eax,4
  988.         mov word ptr [Descriptor  +2 ],ax
  989.         shr eax,16
  990.         mov byte ptr [Descriptor+ 4 ],al
  991. ENDM
  992.  
  993.     Fix_Desc_BASE  PSP_desc        ,fs:[psp_segment]
  994.  
  995.     Fix_Desc_BASE  CODE32_desc    ,CODE32
  996.  
  997.     Fix_Desc_BASE  CODE16_desc    ,CODE16
  998.  
  999.     Fix_Desc_BASE  DATA_desc    ,DATA32
  1000.  
  1001.     Fix_Desc_BASE  DOS_CODE_desc    ,DOS_CODE
  1002.  
  1003.     Fix_Desc_BASE  DOS_DATA_desc    ,DOS_CODE
  1004.  
  1005.     Fix_Desc_BASE  TheStack_desc     , TheSTACK
  1006.  
  1007.  
  1008.  
  1009. ;------------------------- A 2 0     G A T E -------------------------------
  1010. ;                        ENABLE THE A20 GATE
  1011. ; If a XMS Driver is installed then use the Driver to enable the A20
  1012. ; If it's done directly (with 8042) ,the XMS Driver will not have
  1013. ; track of the A20 state and usualy ends up hanging the system.
  1014. ;
  1015. ;-----------------------------------------------------------------------------
  1016.  
  1017.         ; Look for XMS driver installation
  1018.         mov ax,4300h
  1019.         int 2fh
  1020.         cmp al,80h
  1021.         jnz No_XMS
  1022.                              ; ELSE A XMS Driver is installed
  1023.               push ES
  1024.               mov  ax,4310h       ; get Driver entry point
  1025.               int  2fh
  1026.                mov  word ptr xms_Driver,bx
  1027.                mov  word ptr xms_Driver+2,es
  1028.                POP ES
  1029.  
  1030.         ; LOCAL ENABLE A20 GATE
  1031.         mov  ah,05h
  1032.                call xms_Driver
  1033.                cmp ax,1
  1034.                Jz A20_XMS_OK
  1035.         mov dx,offset xms_mesgA20_err
  1036.                 jmp exit_InitError
  1037. A20_XMS_OK:
  1038.  
  1039.                  jmp A20_Controlled            ; ready to go protecded mode
  1040.  
  1041. ;-- Waiting procedures for enabling the A20 directly --
  1042. Wait_until_status_bit0_is_1 proc
  1043. st0_clear:  
  1044.     xor cx,cx
  1045.     in al,64h
  1046.     test al,1
  1047.     jnz st0_set
  1048.     loop st0_clear
  1049.     jmp A20_8042_timeout
  1050. st0_set: ret
  1051. endp
  1052.  
  1053. wait_until_status_bit1_is_0 proc
  1054. st1set:    xor cx,cx
  1055.     in al,64h
  1056.     test al,2
  1057.     jz st1_clear
  1058.     loop st1set
  1059.     jmp A20_8042_timeout
  1060. st1_clear: ret
  1061. endp
  1062. ;----- jumps here if a time out error in enableing the A20 line ---
  1063. A20_8042_timeout:
  1064.         mov dx,offset mesg_TimeOut8042
  1065.  
  1066. exit_InitError:    mov ah,9    ; Prints error mesage and terminates
  1067.         int 21h
  1068.         call free_XMS_memory
  1069.         mov ah,4ch
  1070.         int 21h
  1071.  
  1072.  
  1073. No_XMS:   ;------- Jumps here if no XMS driver is installed ---------------
  1074.  
  1075.  
  1076. ;--- Must enable A20 directly through the 8042 ( keyboard controller)----
  1077. ;     It does this by setting bit 1 of the 8042's output port wich is
  1078. ;     inaccessable to the CPU Bus.
  1079.  
  1080.     cli
  1081.     call wait_until_status_bit1_is_0
  1082.     mov al,0adh                     ;send disable keyboard command
  1083.     out 64h,al                ; viar 8042
  1084.  
  1085.     call wait_until_status_bit1_is_0
  1086.     mov al,0d0h                      ;Send read 8042 output port  cmd
  1087.     out 64h,al
  1088.  
  1089.     call wait_until_status_bit0_is_1
  1090.     in al,60h                     ; read the output port and save it
  1091.     push ax
  1092.  
  1093.     call wait_until_status_bit1_is_0
  1094.     mov al,0d1h                      ; write output port cmd
  1095.     out 64h,al
  1096.  
  1097.     call wait_until_status_bit1_is_0
  1098.     pop ax                           ; write data to the output port
  1099.     or al,2
  1100. ;    and al,not 2
  1101.     out 60h,al                       ; seting bit 1 > enables A20
  1102.  
  1103.     call wait_until_status_bit1_is_0
  1104.      mov al,0aeh                      ;enable keyboard again
  1105.     out 64h,al
  1106.  
  1107.     call wait_until_status_bit1_is_0    ; wait a bit more
  1108.  
  1109.  
  1110.  
  1111.  
  1112. ;----- check if A20 really is enabled -------------
  1113.     mov ax,0FFFFh
  1114.     mov es,ax
  1115.         mov ax,0
  1116.         mov gs,ax
  1117.     mov bl,gs:[0]       ;Compare location 00000000 to 100000h
  1118.         cmp es:[10h],bl     ; Check if the same
  1119.         jnz A20_enabled        ; if not equal then A20 must be on.
  1120.  
  1121.     not byte ptr es:[10h]        ; Cange byte at adreess 100000h.
  1122.         mov bl,es:[10h]
  1123.         mov al,gs:[00]
  1124.     not byte ptr es:[10h]        ; Put back value
  1125.         cmp al,bl              ; Now see if the same
  1126.         jnz A20_enabled
  1127.  
  1128.  
  1129.             ;--- EXIT on A20 error ----
  1130.                 mov dx , offset mesgA20_err
  1131.                 jmp exit_InitError    ; print error mesg and exit
  1132.  
  1133.  
  1134. ; --- A20 is deffently enabled ---
  1135. A20_enabled:
  1136.  
  1137.  
  1138. A20_Controlled:    ; The A20 line should be enabled at this point
  1139.  
  1140.  
  1141. ;-------------------------- A20 ACTIVE ------------------------------------
  1142. ;-----------------------------------------------------------------------------
  1143.  
  1144. ;════════════════════════════════════════════════════════════════════════
  1145. ;══════════════════ SEE IF NEED TO USE DPMI OR NOT  ═════════════════════
  1146. ;════════════════════════════════════════════════════════════════════════
  1147.  
  1148. ;     USE  DPMI TO ENTER  PROTECTED  MODE
  1149.  
  1150.     ; Obtain the Real (V86) to Protected Mode Switch Entry Point
  1151.         mov    ax,1687h
  1152.         int    2Fh
  1153.         and    ax,ax
  1154.         jnz   No_DPMI    
  1155.     mov [DPMI_entry],di        ; DPMI is installed
  1156.     mov [DPMI_entry+2],es
  1157.  
  1158.         mov    fs:[Base_Segment],SS
  1159.  
  1160.         mov    ax,theStack            ; use Protected Mode stack area
  1161.         mov    ss,ax
  1162.         mov    sp,Normal_stack
  1163.  
  1164.  
  1165.     ; Use memory for the DPMI OS private data area
  1166.         mov    es,fs:[Base_Segment]
  1167.      add    fs:Base_Segment,si
  1168.         cmp    fs:Base_Segment,09900h    ; See if enough base memory
  1169.         jae no_mem
  1170.  
  1171.      call Allocate_Base        ; Set descriptor base to here
  1172.  
  1173.     mov    eax,fs:[xms_usage]
  1174.     mov    xms_usage_tmp,eax
  1175.  
  1176.         mov    gs,fs:[psp_segment]         ;Save environment pointer
  1177.         push    word ptr gs:[2Ch]
  1178.  
  1179.  
  1180.         ;  Call the V86 To Protected Mode Switch Entry Point
  1181.         mov    ax,1        ; use 32 DPMI ( big stack )
  1182.         call    dword ptr [DPMI_entry]
  1183.         Jc Cant_Enter_dmpiPMode
  1184.  
  1185.  
  1186.     ;************** NOW IN DPMI PROTECTED MODE ******************
  1187.                ; as a 16 bit but want 32 bit
  1188.  
  1189.         push ds        ; load ES to data segment
  1190.         pop es
  1191.  
  1192.         cmp    xms_usage_tmp,0
  1193.         jz No_DPMI_MEMORY
  1194.  
  1195.         ; Get Free memory info
  1196.         mov    ax,0500h
  1197.         mov     edi,offset Call_data
  1198.         int    31h
  1199.         mov    word ptr Call_data.c_edx,offset dpmi_free_err
  1200.     jc    print_error
  1201.  
  1202.         mov    eax,dword ptr Call_data+08h    ; get lockable size (pages)
  1203.         shl    eax,12            ; convert limit  pages into Bytes
  1204.  
  1205.         ; Only Allocate memory defined in xms_usage
  1206.         cmp    eax,xms_usage_tmp
  1207.         jbe LvDmpiSize
  1208.         mov    eax,xms_usage_tmp
  1209. LvDmpiSize:    mov    xms_usage_tmp,eax
  1210.  
  1211.  
  1212.     mov    ebx,eax
  1213.         shr    ebx,12
  1214.         dec    ebx
  1215.         mov     word ptr [XMS_desc+0],bx    ; Set xms descriptor Limit
  1216.     shr    ebx,16
  1217.         and    bl,0fh
  1218.         or     byte ptr [XMS_desc+6],bl
  1219.  
  1220.         ; Allocate memory Block
  1221.         mov    cx,ax            ; Olny allocate the Lockable memory
  1222.         shr    eax,16
  1223.         mov    bx,ax
  1224.         mov    ax,0501h
  1225.         int    31h
  1226.         mov    word ptr Call_data.c_edx,offset dpmi_aloc_err
  1227.     jc    print_error
  1228.                     ; Returns BX:CX with the linear address
  1229.     mov    word ptr [XMS_Desc+2],cx    ; Set Desciptor base
  1230.     mov    byte ptr [XMS_Desc+4],bl
  1231.         mov    byte ptr [XMS_desc+7],bh
  1232.         mov    _tmpL_xms_base,CX        ; store base address
  1233.         mov    _tmpH_xms_base,BX
  1234.  
  1235. No_DPMI_MEMORY:
  1236.  
  1237. ; Set DPL for all descriptors to CPL
  1238.         mov si,offset GDT + 13
  1239. setDPL:
  1240.     or    byte ptr [si],01100000b
  1241.         add    si,8
  1242.         cmp    si, 12*8 +5
  1243.         jbe setDPL
  1244.  
  1245. ; Allocate 12 descriptors
  1246.     mov    AX,0000h
  1247.     mov    CX,12
  1248.         int    31h
  1249.         mov    word ptr Call_data.c_edx,offset erralc_mesg
  1250.         jc    print_error
  1251.  
  1252.        mov    DPMI_Selector,ax
  1253.  
  1254.  
  1255.     ;---- Set Descriptors -----
  1256.     xor    esi,esi
  1257. set_Descr:
  1258.         mov    ax,000Ch               ; Set Descriptor
  1259.         mov    bx,DPMI_Selector
  1260.         push    bx
  1261.         mov    edi,offset GDT +8
  1262.         mov    edx,esi         
  1263.         shl    edx,3
  1264.         add    edi,edx
  1265.         int    31h
  1266.         mov    word ptr Call_data.c_edx,offset errset_mesg
  1267.     jc    print_error
  1268.  
  1269.         mov    ax,0003h        ; Get Next Selector incremental value
  1270.         int    31h
  1271.         add    DPMI_Selector,ax
  1272.         inc    esi
  1273.     cmp    esi,12        ; must set 12 descriptors
  1274.         jb set_Descr
  1275.  
  1276.         pop DS        ; Pop all the selector values that were pushed.
  1277.  
  1278. ASSUME  DS:DATA32
  1279.         MOV DATA_sel,DS
  1280.  
  1281.     POP  CODE16_sel
  1282.     POP  CODE32_sel
  1283.     POP  PSP_sel
  1284.     POP  DOS_DATA_sel
  1285.     POP  DOS_CODE_sel
  1286.     POP  TheStack_sel
  1287.     POP  VIDEO_sel
  1288.     POP  BASE_sel
  1289.     POP  XMS_sel
  1290.     POP  FLAT_CODE32_sel
  1291.     POP  FLAT_DATA_sel
  1292.  
  1293.         mov    es,[PSP_Sel]        ; Restore environment pointer
  1294.         pop    word ptr es:[02Ch]
  1295.  
  1296.  
  1297.  
  1298.  
  1299.         mov es,DOS_data_sel
  1300. ASSUME    ES:DOS_CODE
  1301.  
  1302.  
  1303.     mov    eax,ES:xms_usage_tmp
  1304.     mov    xms_usage,eax          ; return store the acual amout allocted
  1305.  
  1306.     mov    eax,dword ptr ES:_tmpL_xms_base
  1307.     mov    xms_base,eax        ; store the base address
  1308.  
  1309.  
  1310.         ; Get the base interrupt values of the PIC's
  1311.         mov    ax,0400h
  1312.         int    31h
  1313.         mov    ES:PIC1_base,dh
  1314.         mov    ES:PIC2_base,dl
  1315.  
  1316.         mov ax,0205h
  1317.         mov cx,Code32_sel
  1318.  
  1319.         ; set int vector
  1320. setdmpiInts macro in
  1321.         mov edx,offset irq&in
  1322.         int 31h
  1323.         inc bl
  1324. endm
  1325.  
  1326.         mov bl,es:PIC1_base
  1327. x=0
  1328. rept 8
  1329.     setdmpiInts %x
  1330. x=x+1
  1331. endm
  1332.         mov bl,es:PIC2_base
  1333. x=8
  1334. rept 8
  1335.     setdmpiInts %x
  1336. x=x+1
  1337. endm
  1338.  
  1339.     mov    edx,offset DPMI_EmulateRealInterupt
  1340.         mov    bl,20h
  1341.         int    31h
  1342.  
  1343.     mov    ss,[TheStack_sel]
  1344.         mov    ss:[Real_ESP],0
  1345.         mov    ss:[Real_SS],0
  1346.  
  1347.     mov    esp,Normal_Stack
  1348.  
  1349.         mov es:DPMI_entry,offset start32
  1350.         mov ax,CODE32_sel
  1351.         mov es:DPMI_entry+2,ax
  1352.  
  1353.  
  1354.     ;-----  Jump to 32bit mode through CODE 32 descriptor -----
  1355.         jmp dword ptr es:DPMI_entry
  1356.  
  1357.  
  1358. ASSUME DS:DOS_CODE
  1359.  
  1360. print_error:
  1361.         push    Call_data.c_edx
  1362.         mov    Call_data.c_edx,offset all_DPMI_err
  1363.         call print
  1364.         pop    Call_data.c_edx
  1365.         call print
  1366. dpmi_exit:
  1367.         mov ah,4ch
  1368.         int 21h
  1369.  
  1370. print proc  near
  1371.         mov    Call_data.c_eax,0900h
  1372.         mov    Call_data.c_DS,DOS_CODE
  1373.         mov    ax,0300h        ; sim real int
  1374.         mov    bl,21h
  1375.         mov     bh,0
  1376.         mov    edi,offset call_data
  1377.         xor    cx,cx
  1378.     int    31h
  1379.     ret
  1380. endp
  1381.  
  1382.  
  1383.  
  1384. No_DPMI:
  1385. ;════════════════════════════════════════════════════════════════════════════
  1386. ; Jups here if the operating system dos not support DPMI.
  1387. ; Must enter protected mode directly.
  1388. ;
  1389. ;════════════════════════════════════════════════════════════════════════════
  1390. ;∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·
  1391.  
  1392.     ; See if in V86 mode Because if so we can't go any further
  1393.         smsw ax                ; Not allowed to use,  MOV EAX,CR0
  1394.         test al,1
  1395.         jz in_Real_mode
  1396.               mov dx,offset _inV86_err
  1397.               jmp exit_InitError
  1398.  
  1399. in_Real_mode:
  1400.        ;    See if enough base memory
  1401.         cmp fs:Base_Segment,09A00h
  1402.         ja no_mem
  1403.  
  1404.     cmp xms_driver,00
  1405.         jz No_XMS_MEMORY
  1406.  
  1407. ;∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·
  1408. ; Use the XMS services to allocate extended memoey
  1409.             cmp    fs:xms_usage,0
  1410.             jz Extended_mem_set
  1411.  
  1412.                ; Must have XMS V3.0 to work
  1413.                mov    ah,00        ; Get XMS Version number
  1414.                call    XMS_Driver
  1415.                cmp    ah,3
  1416.                jae xms_V3
  1417. ;              mov dx,offset xms_vers_err
  1418. ;              jmp exit_InitError
  1419. xms_V3:
  1420.  
  1421.  
  1422.                  ; QUERY FREE EXTENDED MEMORY
  1423.                MOV    AH,08h
  1424.                call    XMS_Driver         ; returns eax with KB free
  1425.                and    eax,0ffffh
  1426.                and    al,0FCh        ; want page granular
  1427.                shl    eax,10            ; put KB -> bytes
  1428.  
  1429.             ;Only Allocate memory defined in xms_usage
  1430.                 cmp    eax,fs:xms_usage
  1431.                 jbe LvXmsSize
  1432.         mov    eax,fs:xms_usage
  1433. LvXmsSize:    mov    fs:xms_usage,eax
  1434.  
  1435.                 mov    edx,eax
  1436.                 shr    edx,10
  1437.                and    dl,0FCh            ; want page granular
  1438.  
  1439.                 call    set_xms_limit        ; set limit to eax
  1440.  
  1441.                 ; ALLOCATE ANY EXTENDED MEMORY BLOCK ( size in eDX )
  1442.          mov    ah,09h
  1443.                 call    XMS_Driver
  1444.                 cmp ax,1
  1445.                 jz xms_allod
  1446.          mov dx,offset xms_alloc_err
  1447.                 jmp exit_InitError
  1448. xms_allod:
  1449.                 mov    XMS_handle,dx
  1450.  
  1451.                 ; LOCK THE ALLOCATED EXTENDED MEMORY BLOCK
  1452.         mov    ah,0ch
  1453.                 mov    dx,XMS_handle
  1454.                 call    XMS_Driver
  1455.                 cmp ax,1
  1456.                 jz xms_locked
  1457.          mov dx,offset xms_lock_err
  1458.                 jmp exit_InitError
  1459. xms_locked:                              ; DX:BX has "PHYSICAL" address.
  1460.             mov    word ptr [XMS_Desc+2],bx    ;set xms descriptor
  1461.         mov    byte ptr [XMS_Desc+4],dl    ; Base.
  1462.         mov    byte ptr [XMS_Desc+7],dh
  1463.         mov    word ptr fs:xms_base,BX        ; set base of block
  1464.         mov    word ptr fs:xms_base+2,DX
  1465.  
  1466.         jmp Extended_mem_set
  1467.  
  1468.  
  1469. No_XMS_MEMORY:
  1470. ;∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·
  1471. ; ALLOCATE EVERY SINGLE BYTE OF EXTENDED MEMORY IF NO XMS DRIVER IS INSTALLED
  1472.  
  1473.             ; GET EXTENDED MEMORY SIZE FROM CMOS RAM -
  1474.                 mov al,24   ; get MSB
  1475.         out 70h,al
  1476.                 in  al,71h
  1477.                 shl ax,8
  1478.                 mov al,23   ; get LSB
  1479.         out 70h,al
  1480.                 in  al,71h
  1481.  
  1482.                 and    eax,0ffffh
  1483.                 shl    eax,10
  1484.                mov    fs:xms_usage,eax
  1485.                 call    set_xms_limit        ; set limit to eax
  1486.         mov    fs:xms_base,100000h    ; start block at 1MB
  1487. Extended_mem_set:
  1488. ;∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·
  1489.  
  1490. ; Extended memory is allocated at this point
  1491.  
  1492.     CLI
  1493.         in al,21h
  1494.         mov oirqMask,al
  1495.         in al,0a1h
  1496.         mov oirqMask+1,al
  1497.  
  1498.         ;-- remap IRQ int vectors ---
  1499.     mov    bl,Pic_Base
  1500.         mov    bh,Pic_Base+8
  1501.     call    set_8259intvec
  1502.  
  1503.        mov al,oirqMask
  1504.        out 21h,al
  1505.        mov al,oirqMask+1
  1506.        out 0A1h,al
  1507.  
  1508.     cli
  1509.  
  1510. ;    THE INTERRUPT DESCRIPTOR TABLE
  1511.  
  1512. ; Use memory for the Interrupt Descriptor Table and the TSS
  1513.  
  1514.         mov    ax,fs:Base_Segment        ; Set IDT Reg base
  1515.         mov    es,ax
  1516.         and    eax,0ffffh
  1517.         shl    eax,4
  1518.         mov    dword ptr IDTR_value+2,eax
  1519.         mov    fs:[IDT_base],eax
  1520.  
  1521.         xor    eax,eax            ; Clear all the new memory
  1522.         xor    edi,edi
  1523.         mov    ecx,(8*256 +TSS_Ends+16)/4
  1524.     cld
  1525.         rep    stosd
  1526.  
  1527.  
  1528.         ;--- Build the Interrupt Descriptor Table ---
  1529.     mov    eax,InterruptGATE_a
  1530.     mov    edx,InterruptGATE_B
  1531.         xor    cl,cl
  1532.         xor    si,si
  1533. @MakeIDT:
  1534.     mov    es:[si],eax        ; Put into memory
  1535.     mov    es:[si+4],edx        ; Put into memory
  1536.         add    si,8
  1537.     dec    cl
  1538.     jnz @MakeIDT
  1539.  
  1540.  
  1541.         ;---- Set interrupt vector 31h  ------
  1542.         mov    word ptr es:[31h*8],offset MyDPMI_services
  1543.  
  1544.         ;---- Set interrupt vector 21h  ------
  1545.     mov    word ptr es:[21h*8],offset Go_REAL_MODE
  1546.     mov    word ptr es:[21h*8+2], Dos_Code_desc - GDT
  1547.  
  1548.     ; ---- Set hardware and exception interrupt handlers  --------
  1549. setexecp macro n
  1550.     mov    word ptr es:[n*8],offset _386exception_&n
  1551.            mov    word ptr es:[(Pic_Base+n)*8],offset firstIRQ&n
  1552. endm
  1553. x=0
  1554. rept 16
  1555. setexecp %x
  1556. x=x+1
  1557. endm    
  1558.  
  1559.     ; ---- Set general protection exception handler interrupt --------
  1560.     mov    word ptr es:[13*8],offset General_Exeption_Handler
  1561.  
  1562.     ; ---- Set real mode interrupt emulation handler interrupt --------
  1563.     mov    word ptr es:[20h*8],offset My_EmulateRealInterupt
  1564.  
  1565.  
  1566.     ;-- Build the Task State Segment --
  1567.     add    fs:Base_Segment,80h
  1568.         mov    es,fs:Base_Segment
  1569.  
  1570.  
  1571.  
  1572.         xor eax,eax    ; Get TSS base address
  1573.         mov ax,es
  1574.         shl eax,4
  1575.                                         
  1576.         mov fs:tss_Level0ESP,eax        ; Store address level0 ESP of TSS
  1577.         add fs:tss_Level0ESP,offset tss_esp0
  1578.  
  1579.     mov    MyMain_TSS_Desc+2,ax    ; Load Base address of TSS descriptor
  1580.         shr    eax,16
  1581.     mov    byte ptr MyMain_TSS_Desc+4,al
  1582.  
  1583.  
  1584.  
  1585. ;  Load important TSS fields
  1586.    ; The level0 ESP field is set when real mode interrupt emulation is called
  1587.     mov    es:tss_ss0, TheSTACK_Desc - GDT        ; Priv. 0 SS
  1588.     mov    es:tss_iobase, 068h
  1589.     mov    es:tss_ioend,11111111b
  1590.  
  1591. ; TSS is now built . Time to set the base descriptor base address just
  1592. ; after the TSS and IDT.
  1593.  
  1594.     add    fs:Base_Segment,(TSS_Ends+15)/16        ; inc Base_Segment
  1595.     call    Allocate_Base
  1596.  
  1597.     CLI        ; Can't have interrupts anymore
  1598.  
  1599. ;    Load the Interrupt descriptor table register
  1600.             lidt    qword ptr IDTR_value
  1601.  
  1602. ;    Load the Global descriptor table register
  1603.         mov EAX,DOS_CODE
  1604.                 shl EAX,4
  1605.                 add dword ptr  GDTR_value+2 , EAX
  1606.                 lgdt qword ptr GDTR_value
  1607.  
  1608. ; Enter Protected Mode
  1609.     mov    eax,CR0
  1610.     or    al,1            ; Set PE bit of CR0
  1611.     mov    CR0,eax
  1612.  
  1613.         jmp FlushP            ; Flush instruction prefetch counter
  1614.  
  1615. FlushP:
  1616.  
  1617.  
  1618.         mov    ax,MyMain_TSS_Desc - GDT    ; Set TR to any valid TSS
  1619.         ltr    ax
  1620.  
  1621.         mov    ax,data_desc - GDT
  1622.         mov    ds,ax
  1623. assume ds:data32
  1624.  
  1625.     mov    ss,ds:[TheStack_sel]         ; Setup Protected mode stack
  1626.     mov    esp,Normal_Stack
  1627.  
  1628.     mov    SS:[Real_SS],V86_Stack        ; Setup initial V86 stack
  1629.     mov    SS:[Real_ESP ],V86_stack_size
  1630.  
  1631.         db 0EAh            ; Jump to 32bit mode through CODE 32 descr
  1632.         dw offset Setup_Pmode , Code32_Desc - GDT
  1633. ;--------------------------------------------------------------------------
  1634. ;         END OF PROTECTED MODE INITALIZATION
  1635. ;--------------------------------------------------------------------------
  1636.  
  1637. ;----------------------------------------------------------------------------
  1638. ;─────────────────────  INTERNAL ROUTINES ───────────────────────────────────
  1639. ;----------------------------------------------------------------------------
  1640. assume ds:dos_code
  1641. ;∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·
  1642. set_xms_limit proc
  1643.                     ; Set the xms descriptor limit.
  1644.             shr    eax,12
  1645.             dec    eax
  1646.         mov    word ptr [XMS_Desc+0],ax    ; set limit [0..15]
  1647.         shr    eax,16
  1648.             or     byte ptr [XMS_desc+6],al        ; limit [16..19]
  1649.         ret
  1650. endp
  1651.  
  1652.  
  1653. ;∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·
  1654. Allocate_Base    proc
  1655.         mov    ax,fs:Base_Segment    ; Set BASE data descriptor to this
  1656.         and    eax,0ffffh
  1657.         shl    eax,4
  1658.         mov    word ptr [Base_Desc +2 ],ax
  1659.         shr    eax,16
  1660.         mov    byte ptr [Base_Desc +4 ],al
  1661.     ret
  1662. ENDP
  1663. ;∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·
  1664. exit_error:    mov     ah,9        ; print error message
  1665.             int    21h
  1666.             jmp Exit_To_MSDOS
  1667.  
  1668. ;∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·
  1669. Cant_Enter_dmpiPMode:    mov dx,offset pmiERr
  1670.                 jmp exit_error
  1671.  
  1672. No_Mem:            mov dx,offset No_Mem_err
  1673.                 jmp exit_error
  1674.  
  1675.  
  1676. align 16
  1677. NON_DPMI_initalize_Size equ $ - NON_DPMI_initalize_start:
  1678.  
  1679. dosstart endp
  1680. DOS_CODE ENDS
  1681.  
  1682. TheSTACK    SEGMENT public stack 'stack' USE32
  1683. db    Normal_stack dup (?)
  1684. TheSTACK    ENDS
  1685.  
  1686. V86_STACK    SEGMENT public stack 'stack' USE16
  1687. db    V86_stack_size dup (?)
  1688. V86_STACK    ENDS
  1689.  
  1690.  
  1691. END   DosStart
  1692.