home *** CD-ROM | disk | FTP | other *** search
/ The Unsorted BBS Collection / thegreatunsorted.tar / thegreatunsorted / programming / asm_programming / PMODE.ASM < prev    next >
Assembly Source File  |  1993-06-07  |  69KB  |  2,035 lines

  1. ; PMODE v2.1232 raw, DPMI, VCPI, & XMS compliant protected mode header.
  2. ; By Tran (a.k.a. Thomas Pytel) of Renaissance.
  3.  
  4.         .386p
  5.  
  6. LOWMIN          = 0             ; minimum free low memory (in K)
  7. EXTMIN          = 0             ; minimum free extended memory (in K)
  8. STAKLEN         = 100h          ; stack size in para (keep below or = 1000h)
  9. STAKSAFE        = 20h           ; safe stack space in para
  10.  
  11. code16  segment para public use16
  12. code16  ends
  13. code32  segment para public use32
  14. code32  ends
  15. codeend segment para stack use32 'stack'
  16. codeend ends
  17.  
  18. ;▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓
  19. ; Real mode and 16bit code
  20. ;▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓
  21. code16  segment para public use16
  22.         assume cs:code16, ds:code16
  23.         org 0
  24.  
  25. ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
  26. ; 16 bit common system data
  27. ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
  28. errmsg0         db      '386 or better not detected!!!',7,'$'
  29. errmsg1         db      'Not enough low memory!!!',7,'$'
  30. errmsg2         db      'This system is already in V86 mode!!!',7,'$'
  31. errmsg3         db      'Not enough extended memory!!!',7,'$'
  32. errmsg4         db      'Couldn''t enable A20 gate!!!',7,'$'
  33. errmsg5         db      'Extended memory allocation failure. (weird eh???)',7,'$'
  34.  
  35. nullint         db      0cfh            ; IRET instruction
  36. exitrout        dw      exit            ; exit routine, modified if XMS, VCPI
  37.  
  38. savedstakoff    dw      ?               ; current saved stack offset
  39. savedstakseg    dw      ?               ; current saved stack segment
  40.  
  41. ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
  42. ; 16 bit common system code
  43. ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
  44. ;═════════════════════════════════════════════════════════════════════════════
  45. intreal:                                ; real mode int, load FS and GS here
  46.         pushf
  47. ;-----------------------------------------------------------------------------
  48. callreal:                               ; real mode call, load FS and GS here
  49.         push cs
  50.         push offset icreald
  51.         mov fs,cs:v86r_fs
  52.         mov gs,cs:v86r_gs
  53.         mov eax,cs:v86r_eax
  54.         mov ecx,cs:v86r_ecx
  55.         mov edx,cs:v86r_edx
  56.         mov ebx,cs:v86r_ebx
  57.         mov esi,cs:v86r_esi
  58.         mov edi,cs:v86r_edi
  59.         mov ebp,cs:v86r_ebp
  60. ;-----------------------------------------------------------------------------
  61. icreal:                                 ; real mode int, call, or IRQ
  62.         db 66h,68h              ; PUSH destination addx
  63. icrealm1        dd      ?       ;
  64. icrealm0        db      ?       ; CLI or STI
  65.         retf
  66. ;-----------------------------------------------------------------------------
  67. icreald:                                ; done with real int or call
  68.         cli
  69.         pushf
  70.         pop cs:v86r_flags
  71.         mov cs:v86r_eax,eax
  72.         mov cs:v86r_ecx,ecx
  73.         mov cs:v86r_edx,edx
  74.         mov cs:v86r_ebx,ebx
  75.         mov cs:v86r_esi,esi
  76.         mov cs:v86r_edi,edi
  77.         mov cs:v86r_ebp,ebp
  78.         mov cs:v86r_ds,ds
  79.         mov cs:v86r_es,es
  80.         mov cs:v86r_fs,fs
  81.         mov cs:v86r_gs,gs
  82. icreald2:
  83.         mov ax,cs
  84.         mov ds,ax
  85. icrealm2        label word              ; return to pmode modifiable to JMP
  86. ;-----------------------------------------------------------------------------
  87.         mov ebx,ds:cp_savedstakoff      ; DPMI return to pmode
  88.         mov dx,ds:dp_savedstaksel
  89.         mov edi,offset dp_int3_d
  90.         mov si,ds:_selcode
  91.         mov cx,dx
  92.         mov ax,ds:_seldata
  93.         jmp ds:d_switchaddx
  94. ;-----------------------------------------------------------------------------
  95. VICREAL1D=(($-(icrealm2+2))shl 8)+0ebh
  96. v_icreal1d:                             ; VCPI return to pmode from safe
  97.         mov edi,offset cp_int3_d
  98. ;-----------------------------------------------------------------------------
  99. ; EDI=offset to jump to in code32
  100. v_switchtopmode:                        ; VCPI switch to pmode
  101.         mov ds:v_ss_dest,edi
  102.         mov esi,offset v_ss_cr3
  103.         add esi,ds:_code16a
  104.         mov ax,0de0ch
  105.         int 67h
  106. ;-----------------------------------------------------------------------------
  107. CICREAL1D=(($-(icrealm2+2))shl 8)+0ebh
  108. c_icreal1d:                             ; custom return to pmode from safe
  109.     mov edi,offset cp_int3_d
  110. ;-----------------------------------------------------------------------------
  111. ; EDI=offset in pmode to jump to
  112. c_retpmode:                             ; reenter 32bit pmode
  113.         lgdt fword ptr c_gdt32addx      ; set up pmode GDT and IDT
  114.     lidt fword ptr c_idt32addx
  115.     mov ds:gdt32task[5],89h     ; set task as not busy
  116.         mov eax,cr0                     ; switch to pmode
  117.         or al,1
  118.         mov cr0,eax
  119.         db 0eah
  120.         dw $+4,20h
  121.         mov ax,30h                      ; load task register
  122.         ltr ax
  123.     jmp c_gotopmode
  124. ;-----------------------------------------------------------------------------
  125. if ($-(icrealm2+2)) gt 127
  126.   err
  127. endif
  128. CICREAL0D=(($-(icrealm2+2))shl 8)+0ebh
  129. c_icreal0d:                             ; return to pmode from normal
  130.         int 0ffh
  131. ;═════════════════════════════════════════════════════════════════════════════
  132. int32:                                  ; real mode INT32: EDX=off
  133.         pushad
  134.         push ds es fs gs
  135.         cli
  136.         mov ax,cs
  137.         mov ds,ax
  138.         mov ds:p_cpmodem0,edx
  139.         mov al,[esp+45]
  140.         shr al,1
  141.         and al,1
  142.         add al,0fah
  143.         mov ds:p_cpmodem1,al
  144.         push savedstakoff
  145.         push savedstakseg
  146.         movzx ebx,ds:nextmodestack
  147.         lea eax,[ebx-STAKSAFE*16]
  148.         mov ds:nextmodestack,ax
  149.         add ebx,ds:realstackbase
  150.         mov savedstakseg,ss
  151. int32m0         label   word            ; jump to pmode, modifiable
  152. ;-----------------------------------------------------------------------------
  153.         sub sp,ds:dp_savelen
  154.         mov savedstakoff,sp
  155.         mov ax,ss                       ; DPMI jump to pmode
  156.         mov es,ax
  157.         mov di,sp
  158.         xor al,al
  159.         call d_saveaddx
  160.         mov ax,ds:_seldata
  161.         mov cx,ax
  162.         mov dx,ax
  163.         mov edi,offset p_cpmode
  164.         mov si,ds:_selcode
  165.         jmp ds:d_switchaddx
  166. ;-----------------------------------------------------------------------------
  167. VINT32=(($-(int32m0+2))shl 8)+0ebh
  168. v_int32:                                ; VCPI call pmode
  169.         push ds:p_cpmodem2
  170.         mov ds:p_cpmodem2,VCPMODED
  171.         mov savedstakoff,sp
  172.         mov edi,offset p_cpmode1
  173.         jmp v_switchtopmode
  174. ;-----------------------------------------------------------------------------
  175. if ($-(int32m0+2)) gt 127
  176.   err
  177. endif
  178. CINT32=(($-(int32m0+2))shl 8)+0ebh
  179. c_int32:                                ; raw/XMS call pmode
  180.         push ds:p_cpmodem2
  181.         mov ds:p_cpmodem2,CCPMODED
  182.         mov savedstakoff,sp
  183.         mov edi,offset p_cpmode1
  184.         jmp c_retpmode
  185. ;═════════════════════════════════════════════════════════════════════════════
  186. int32d0:                                ; DPMI done with pmode call
  187.         mov di,sp
  188.         mov al,1
  189.         call d_saveaddx
  190.         add sp,ds:dp_savelen
  191. ;-----------------------------------------------------------------------------
  192. int32d2:                                ; done from all
  193.         pop savedstakseg
  194.         pop savedstakoff
  195.         add ds:nextmodestack,STAKSAFE*16
  196.         mov bx,ds:v86r_flags
  197.         mov ax,[esp+44]
  198.         and ax,not 8d5h
  199.         and bx,8d5h
  200.         or ax,bx
  201.         mov [esp+44],ax
  202.         pop gs fs es ds
  203.         popad
  204.         iret
  205. ;═════════════════════════════════════════════════════════════════════════════
  206. int32d1:                                ; VCPI done with pmode call
  207.         mov ss,savedstakseg
  208.         pop ds:p_cpmodem2
  209.         jmp int32d2
  210. ;═════════════════════════════════════════════════════════════════════════════
  211. int32d3:                                ; raw/XMS done with pmode call
  212.         mov c_retreal0m0,offset c_sicreal
  213.         mov ax,cs
  214.         mov ds,ax
  215.         movzx esp,savedstakoff
  216.         mov ss,savedstakseg
  217.         pop ds:p_cpmodem2
  218.         jmp int32d2
  219. ;─────────────────────────────────────────────────────────────────────────────
  220. chek_VCPI:                              ; Chek for VCPI
  221.         mov dx,offset v_emmname
  222.         mov ax,3d00h
  223.         int 21h
  224.         jc short chekVCPIa
  225.         mov bx,ax
  226.         mov ax,4400h
  227.         int 21h
  228.         jc short chekVCPIa
  229.         test dh,80h
  230.         jz short chekVCPIa
  231.         mov ax,4407h
  232.         int 21h
  233.         mov dl,al
  234.         mov ah,3Eh
  235.         int 21h
  236.         cmp dl,0FFh
  237.         jne short chekVCPIa
  238.         mov bx,1
  239.         mov ah,43h
  240.         int 67h
  241. ;       or ah,ah
  242. ;       jnz short chekVCPIa
  243.         mov v_emshandle,dx
  244.         mov ax,0de00h
  245.         int 67h
  246.         or ah,ah
  247.         clc
  248.         jz short chekVCPId
  249.         mov ah,45h
  250.         int 67h
  251. chekVCPIa:
  252.         stc
  253. chekVCPId:
  254.         ret
  255. ;─────────────────────────────────────────────────────────────────────────────
  256. chek_processor:                         ; Detect if current processor 386
  257.         pushf
  258.         xor ah,ah
  259.         push ax
  260.         popf
  261.         pushf
  262.         pop ax
  263.         and ah,0f0h
  264.         cmp ah,0f0h
  265.         je short detectno386
  266.         mov ah,0f0h
  267.         push ax
  268.         popf
  269.         pushf
  270.         pop ax
  271.         and ah,0f0h
  272.         jz short detectno386
  273.         popf
  274.         ret
  275. detectno386:
  276.         mov dx,offset errmsg0
  277.         jmp short exit16err
  278. ;─────────────────────────────────────────────────────────────────────────────
  279. chek_V86:                               ; Chek if already in V86 mode
  280.         smsw ax
  281.         test al,1
  282.         mov dx,offset errmsg2
  283.         jnz short exit16err
  284.         ret
  285. ;─────────────────────────────────────────────────────────────────────────────
  286. pregetlomem:                            ; Get low memory or abort
  287.         add eax,ds:_lomembase
  288.         mov ebx,ds:_lomemtop
  289.         cmp eax,ebx
  290.         ja short pregetlomema
  291.         mov ecx,eax
  292.         xchg eax,ds:_lomembase
  293.         sub ebx,ecx
  294.         cmp ebx,LOWMIN*1024
  295.         jb short pregetlomema
  296.         ret
  297. pregetlomema:
  298.         mov dx,offset errmsg1
  299. ;─────────────────────────────────────────────────────────────────────────────
  300. exit16err:                              ; Exit program with message
  301.         mov ah,9
  302.         int 21h
  303.         jmp exitrout
  304. ;-----------------------------------------------------------------------------
  305. exit:                                   ; Guess what???
  306.         mov ah,4ch
  307.         int 21h
  308. ;═════════════════════════════════════════════════════════════════════════════
  309. start16:                                ; Program begins here
  310.         cli
  311.         cld
  312.         push cs
  313.         pop ds
  314.  
  315.         call chek_processor             ; is it at least a 386¿
  316.  
  317.         mov ax,es                       ; set up a bunch of pointers
  318.         movzx eax,ax
  319.         shl eax,4
  320.         mov ds:_pspa,eax
  321.         mov eax,code16
  322.         shl eax,4
  323.         mov ds:_code16a,eax
  324.         or dword ptr ds:gdt32code16[2],eax
  325.         or dword ptr ds:gdt32data16[2],eax
  326.         mov ebx,code32
  327.         shl ebx,4
  328.         mov ds:_code32a,ebx
  329.         or dword ptr ds:gdt32code32[2],ebx
  330.         or dword ptr ds:gdt32data32[2],ebx
  331.         add dword ptr ds:c_gdt32addx[2],ebx
  332.         mov eax,codeend
  333.         shl eax,4
  334.         sub eax,ebx
  335.         mov ds:_lomembase,eax
  336.         mov ds:realstackbase,eax
  337.         movzx eax,word ptr es:[2]
  338.         shl eax,4
  339.         sub eax,ebx
  340.         mov ds:_lomemtop,eax
  341.  
  342.         mov eax,STAKLEN*16              ; get stack memory
  343.         call pregetlomem
  344.  
  345.         push es                         ; save PSP seg (DPMI chek kills ES)
  346.         pop fs
  347.  
  348.         mov ax,1687h                    ; chek for DPMI
  349.         int 2fh
  350.         or ax,ax
  351.         jz d_start
  352.  
  353.         call chek_VCPI                  ; chek for VCPI
  354.         jnc v_start
  355.  
  356.         call chek_V86                   ; chek for V86 mode
  357.  
  358.         mov ax,4300h                    ; chek for XMS
  359.         int 2fh
  360.         cmp al,80h
  361.         je x_start
  362.  
  363.         jmp c_start                     ; custom system start
  364. ;─────────────────────────────────────────────────────────────────────────────
  365. enableA20:                              ; hardware enable gate A20
  366.         xor ax,ax
  367.         mov fs,ax
  368.         dec ax
  369.         mov gs,ax
  370.         call testA20
  371.         je short enableA20done
  372.         in al,92h                       ; PS/2 A20 enable
  373.         or al,2
  374.         jmp short $+2
  375.         jmp short $+2
  376.         jmp short $+2
  377.         out 92h,al
  378.         call testA20
  379.         je short enableA20done
  380.         call enableA20o1                ; AT A20 enable
  381.         jnz short enableA20wait
  382.         mov al,0d1h
  383.         out 64h,al
  384.         call enableA20o1
  385.         jnz short enableA20wait
  386.         mov al,0dfh
  387.         out 60h,al
  388.         push offset enableA20wait
  389. enableA20o1:
  390.         mov ecx,20000h
  391. enableA20o1l:
  392.         jmp short $+2
  393.         jmp short $+2
  394.         jmp short $+2
  395.         in al,64h
  396.         test al,2
  397.         loopnz enableA20o1l
  398. enableA20done:
  399.         ret
  400. ;-----------------------------------------------------------------------------
  401. enableA20wait:                          ; wait for A20
  402.         mov al,36h
  403.         out 43h,al
  404.         xor al,al
  405.         out 40h,al
  406.         out 40h,al
  407.         mov cx,800h
  408. enableA20waitl0:
  409.         call testA20
  410.         je enableA20done
  411.         in al,40h
  412.         in al,40h
  413.         mov ah,al
  414. enableA20waitl1:
  415.         in al,40h
  416.         in al,40h
  417.         cmp al,ah
  418.         je enableA20waitl1
  419.         loop enableA20waitl0
  420.         mov dx,offset errmsg4
  421.         jmp exit16err
  422. ;-----------------------------------------------------------------------------
  423. testA20:                                ; Test for enabled A20
  424.         mov al,fs:[0]
  425.         mov ah,al
  426.         not al
  427.         mov gs:[10h],al
  428.         cmp ah,fs:[0]
  429.         mov fs:[0],ah
  430.         ret
  431. ;─────────────────────────────────────────────────────────────────────────────
  432. ; BL=low PIC val, BH=high PIC val
  433. setintslots:                            ; set int nums in table to PIC vals
  434.         mov edi,offset ds:intslottbl
  435.         mov cl,8
  436. setintslotsl0:
  437.         mov [di],bl
  438.         inc di
  439.         inc bl
  440.         dec cl
  441.         jnz setintslotsl0
  442.         mov cl,8
  443. setintslotsl1:
  444.         mov [di],bh
  445.         inc di
  446.         inc bh
  447.         dec cl
  448.         jnz setintslotsl1
  449.         ret
  450.  
  451. ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
  452. ; 16 bit DPMI system data
  453. ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
  454. d_errmsg0       db      'DPMI host is not 32bit!!!',7,'$'
  455. d_errmsg1       db      'Ran out of DPMI descriptors!!!',7,'$'
  456. d_errmsg2       db      'Couldn''t set DPMI descriptors as needed!!!',7,'$'
  457.  
  458. d_enterpmode    dw      ?,?             ; DPMI switch to pmode addx
  459. d_pspsel        dw      ?               ; stupid PSP selector
  460. d_oldenvsegsel  dw      ?               ; stupid selector we dont want
  461.  
  462. d_switchaddx    dd      ?               ; switch to pmode addx
  463. d_saveaddx      dd      ?               ; save/restore state addx
  464.  
  465. d_nintoff       dd      offset dp_irq0,offset dp_irq1,offset dp_irq2,offset dp_irq3
  466.                 dd      offset dp_irq4,offset dp_irq5,offset dp_irq6,offset dp_irq7
  467.                 dd      offset dp_irq8,offset dp_irq9,offset dp_irqa,offset dp_irqb
  468.                 dd      offset dp_irqc,offset dp_irqd,offset dp_irqe,offset dp_irqf
  469.                 dd      offset dp_int33,offset dp_int32,offset dp_int33,offset dp_int32
  470. ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
  471. ; 16 bit DPMI system code
  472. ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
  473. ;═════════════════════════════════════════════════════════════════════════════
  474. d_retreal:                              ; Return to real mode
  475.         mov ax,205h                     ; restore all int vektorz needed
  476.         mov edi,19
  477. d_retreall0:
  478.         mov bl,ds:intslottbl[edi]
  479.         lea ebp,[edi*2+edi]
  480.         mov edx,dword ptr ds:dp_ointbuf[ebp*2]
  481.         mov cx,word ptr ds:dp_ointbuf[ebp*2+4]
  482.         int 31h
  483.         sub di,1
  484.         jnc d_retreall0
  485.         jmp short d_exit
  486. ;─────────────────────────────────────────────────────────────────────────────
  487. d_exit16err:                            ; DPMI Exit with error message
  488.         mov ds:v86r_ds,code16
  489.         mov ds:v86r_ah,9
  490.         mov ax,300h
  491.         mov bx,21h
  492.         xor cx,cx
  493.         mov edi,offset ds:v86r_edi
  494.         push ds
  495.         pop es
  496.         int 31h
  497. ;─────────────────────────────────────────────────────────────────────────────
  498. d_exit:                                 ; DPMI exit to real mode
  499.         mov es,d_pspsel                 ; restore env selector
  500.         mov ax,d_oldenvsegsel
  501.         mov es:[2ch],ax
  502.         jmp exit
  503. ;═════════════════════════════════════════════════════════════════════════════
  504. d_start:                                ; Start in a crappy DPMI system
  505.         or ds:_sysbyte0,3               ; set system type DPMI byte
  506.  
  507.         test bl,1                       ; must be 32bit DPMI
  508.         mov dx,offset d_errmsg0
  509.         jz exit16err
  510.  
  511.         mov d_enterpmode[0],di          ; store enter addx
  512.         mov d_enterpmode[2],es
  513.         push word ptr fs:[2ch]          ; preserve old env seg
  514.  
  515.         movzx eax,si                    ; get mem for DPMI blok
  516.         shl eax,4
  517.         call pregetlomem
  518.         shr eax,4
  519.         add ax,code32
  520.         mov es,ax
  521.  
  522.         mov ax,1                        ; switch to pmode
  523.         call dword ptr d_enterpmode
  524.         cli                             ; I don't trust DPMI
  525.         mov dx,offset d_errmsg1
  526.         jc exit16err
  527.         mov ds:v86r_dx,dx               ; prepare for abort maybe
  528.         pop ax                          ; swap old env seg with selector
  529.         xchg ax,es:[2ch]
  530.         mov d_oldenvsegsel,ax
  531.         mov d_pspsel,es                 ; store stupid selectors
  532.         mov ds:data16sel,ds
  533.         mov ds:code16sel,cs
  534.         mov ds:code16off,offset d_retreal       ; set return to real mode addx
  535.         mov ds:_setirqvect,offset dp_setirqvect ; modify some crap
  536.         mov ds:_getirqvect,offset dp_getirqvect
  537.  
  538.         push ds                         ; no more need for PSP
  539.         pop es
  540.         mov ax,3                        ; get selector increment value
  541.         int 31h
  542.         mov bx,ax
  543.         xor ax,ax                       ; get 3 needed descriptors
  544.         mov cx,3
  545.         int 31h
  546.         jc d_exit16err
  547.  
  548.         mov si,ax                       ; set up descriptors
  549.         mov ds:_selcode,ax
  550.         lea ecx,[eax+ebx]
  551.         mov ds:_seldata,cx
  552.         lea ebp,[ecx+ebx]
  553.         mov ds:_selzero,bp
  554.         mov ds:v86r_dx,offset d_errmsg2
  555.         mov ax,0ch                      ; set descriptors from GDT
  556.         mov bx,si
  557.         mov edi,offset ds:gdt32code32
  558.         or byte ptr [edi+5],60h
  559.         int 31h
  560.         jc d_exit16err
  561.         mov bx,cx
  562.         mov edi,offset ds:gdt32data32
  563.         or byte ptr [edi+5],60h
  564.         int 31h
  565.         jc d_exit16err
  566.         mov bx,bp
  567.         mov edi,offset ds:gdt32zero32
  568.         or byte ptr [edi+5],60h
  569.         int 31h
  570.         jc d_exit16err
  571.  
  572.         mov es,cx                       ; ES, FS, and GS what they should be
  573.         mov fs,cx
  574.         mov gs,bp
  575.  
  576.         mov edi,ds:_lomembase           ; chek and get extended memory
  577.         mov eax,ds:_lomemtop
  578.         sub eax,edi
  579.         cmp eax,48
  580.         mov ds:v86r_dx,offset errmsg1
  581.         jb d_exit16err
  582.         mov ax,500h
  583.         int 31h
  584.         mov eax,es:[edi+14h]
  585.         cmp eax,-1
  586.         jne short d_startf0
  587.         mov eax,(EXTMIN+3) shr 2
  588. d_startf0:
  589.         shl eax,12
  590.         mov edx,eax
  591.         shr eax,10
  592.         cmp eax,EXTMIN
  593.         mov ds:v86r_dx,offset errmsg3
  594.         jb d_exit16err
  595.         or edx,edx
  596.         jz short d_startf1
  597.         mov cx,dx
  598.         shld ebx,edx,16
  599.         mov ax,501h
  600.         int 31h
  601.         mov ds:v86r_dx,offset errmsg5
  602.         jc d_exit16err
  603.         shl ebx,16
  604.         mov bx,cx
  605.         sub ebx,ds:_code32a
  606.         mov ds:_himembase,ebx
  607.         add ebx,edx
  608.         mov ds:_himemtop,ebx
  609. d_startf1:
  610.  
  611.         mov ax,305h                     ; get save/restore state addxs
  612.         int 31h
  613.         mov ds:dp_savelen,ax
  614.         mov dword ptr ds:dp_saveaddx[0],edi
  615.         mov word ptr ds:dp_saveaddx[4],si
  616.         mov word ptr d_saveaddx[0],cx
  617.         mov word ptr d_saveaddx[2],bx
  618.         mov ax,306h                     ; get switch mode addxs
  619.         int 31h
  620.         mov dword ptr ds:dp_switchaddx[0],edi
  621.         mov word ptr ds:dp_switchaddx[4],si
  622.         mov word ptr d_switchaddx[0],cx
  623.         mov word ptr d_switchaddx[2],bx
  624.  
  625.         mov ax,400h                     ; set IRQ handlers to PIC values
  626.         int 31h
  627.         xchg dl,dh
  628.         mov bx,dx
  629.         call setintslots
  630.  
  631.         mov ah,2                        ; backup and set all int vektorz
  632.         mov si,ds:_selcode
  633.         mov edi,19
  634. d_startl0:
  635.         mov bl,ds:intslottbl[edi]
  636.         mov al,4
  637.         int 31h
  638.         lea ebp,[edi*2+edi]
  639.         mov dword ptr ds:dp_ointbuf[ebp*2],edx
  640.         mov word ptr ds:dp_ointbuf[ebp*2+4],cx
  641.         mov al,5
  642.         mov edx,d_nintoff[edi*4]
  643.         mov cx,si
  644.         int 31h
  645.         sub di,1
  646.         jnc d_startl0
  647.  
  648.         mov ax,es                       ; set up needed regs & go on to 32bit
  649.         mov ss,ax
  650.         add esp,ds:realstackbase
  651.         mov ds,ax
  652.         push dword ptr cs:_selcode
  653.         push offset p_start
  654.         db 66h,0cbh             ; 32bit RETF
  655.  
  656. ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
  657. ; 16bit VCPI system data
  658. ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
  659. v_errmsg0       db      'Incompatible VCPI PIC mappings!!!',7,'$'
  660.  
  661. v_emmname       db      'EMMXXXX0',0    ; EMS device name
  662. v_emshandle     dw      ?               ; one page allocated to turn on
  663.  
  664. v_pagedirseg    dw      ?               ; seg of page directory
  665. v_pagebase      dw      0               ; first page of himem (*4)+1000h
  666. v_pagetop       dw      0               ; top page of himem (*4)+1000h
  667.  
  668. v_ss_cr3        dd      ?               ; new CR3 for pmode (physical)
  669. v_ss_gdtaddxptr dw      c_gdt32addx,0   ; ptr to GDT data for pmode
  670. v_ss_idtaddxptr dw      c_idt32addx,0   ; ptr to IDT data for pmode
  671. v_ss_ldtsel     dw      0               ; don't need no stinkin LDTs
  672. v_ss_trsel      dw      30h             ; task state segment selector
  673. v_ss_dest       dd      ?               ; start in pmode EIP
  674.                 dw      20h             ; start in pmode CS
  675. ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
  676. ; 16bit VCPI system code
  677. ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
  678. ;═════════════════════════════════════════════════════════════════════════════
  679. v_retreal:                              ; VCPI return to real mode
  680.         movzx edi,exitrout
  681.         mov esi,esp
  682.         sub esi,ds:realstackbase
  683.         mov cx,code16
  684. ;═════════════════════════════════════════════════════════════════════════════
  685. ; EDI=offset to jump to, ESI=real mode stack ptr, CX=real mode DS
  686. v_retreal0:                             ; VCPI go to real mode
  687.         sub esp,8
  688.         push ecx
  689.         push dword ptr ds:v86r_es
  690.         dw 06866h,codeend,0     ; PUSH dword codeend
  691.         push esi
  692.         pushfd
  693.         dw 06866h,code16,0      ; PUSH dword code16
  694.         push edi
  695.         mov ax,gs
  696.         mov ds,ax
  697.         mov ax,0de0ch
  698.         call cs:vp_vcpipmentry
  699. ;─────────────────────────────────────────────────────────────────────────────
  700. v_exit2:                                ; VCPI exit (clean up pages)
  701.         mov es,v_pagedirseg
  702.         mov si,v_pagebase
  703.         mov cx,v_pagetop
  704.         sub cx,si
  705.         jz short v_exit
  706. v_exit2l0:
  707.         mov edx,es:[si]
  708.         and dx,0f000h
  709.         mov ax,0de05h
  710.         int 67h
  711.         add si,4
  712.         sub cx,4
  713.         jnz v_exit2l0
  714. ;─────────────────────────────────────────────────────────────────────────────
  715. v_exit:                                 ; VCPI exit (clean up EMS page)
  716.         mov ah,45h
  717.         mov dx,v_emshandle
  718.         int 67h
  719.         jmp exit
  720. ;─────────────────────────────────────────────────────────────────────────────
  721. v_exiterr1:                             ; VCPI not enough low mem exit
  722.         mov dx,offset errmsg1
  723.         jmp exit16err
  724. ;═════════════════════════════════════════════════════════════════════════════
  725. v_start:                                ; start continues from VCPI
  726.         or ds:_sysbyte0,2               ; set system type VCPI byte
  727.         mov ds:code16off,offset v_retreal       ; VCPI return to real mode
  728.         mov c_idt32handler[48h],offset vp_int33 ; VCPI safe int handlers
  729.         mov c_idt32handler[4ch],offset vp_int32
  730.         mov ds:cp_v86irqintr[4],offset vp_int33f0 ; VCPI IRQ safe int routine
  731.         mov int32m0,VINT32              ; VCPI real INT32
  732.         mov exitrout,offset v_exit      ; set EMS cleanup exit
  733.  
  734.         mov ax,0de0ah                   ; get PIC mappings
  735.         int 67h
  736.         mov bh,cl
  737.         mov dx,offset v_errmsg0         ; chek for compatible PIC mapping
  738.         cmp bl,bh
  739.         je exit16err
  740.         cmp bl,30h
  741.         je exit16err
  742.         cmp bh,30h
  743.         je exit16err
  744.         mov ax,70h                      ; compatible, get highest needed num
  745.         cmp al,bl
  746.         ja short v_startf1
  747.         mov al,bl
  748. v_startf1:
  749.         cmp al,bh
  750.         ja short v_startf2
  751.         mov al,bh
  752. v_startf2:
  753.         add al,7
  754.         mov c_numofintvects,al
  755.         lea eax,[eax*8+7]               ; set limit of IDT
  756.         mov c_idt32addx,ax
  757.         call setintslots                ; set int slots needed
  758.         movzx eax,ax
  759.         add eax,2068h+1
  760.         call pregetlomem                ; allocate TSS, IO bitmap, and IDT
  761.         mov ds:cp_tssesp0ptr,eax
  762.         mov eax,ds:_code16a             ; adjust mode switch structure
  763.         add dword ptr v_ss_gdtaddxptr,eax
  764.         add dword ptr v_ss_idtaddxptr,eax
  765.  
  766.         mov exitrout,offset v_exit2     ; set VCPI cleanup exit
  767.  
  768.         mov eax,ds:_lomembase           ; align lomem base on a page
  769.         mov ebx,ds:_code32a
  770.         add ebx,eax
  771.         lea ecx,[ebx+0fffh]
  772.         and ecx,0fffff000h
  773.         sub ebx,ecx
  774.         sub eax,ebx
  775.         mov ds:_lomembase,eax
  776.         mov ebp,ds:_lomemtop            ; get available low memory
  777.         sub ebp,eax
  778.         sub ebp,LOWMIN*1024             ; die if not enough
  779.         jc v_exiterr1
  780.         cmp ebp,8192
  781.         jb v_exiterr1
  782.  
  783.         shld eax,ecx,28                 ; get segment and clear all pages
  784.         mov v_pagedirseg,ax
  785.         mov es,ax
  786.         xor di,di
  787.         mov cx,2048
  788.         xor eax,eax
  789.         rep stos dword ptr es:[di]
  790.         mov di,1000h                    ; get VCPI pmode interface
  791.         mov esi,offset ds:gdt32vcpi
  792.         mov ax,0de01h
  793.         int 67h
  794.         mov dword ptr ds:vp_vcpipmentry,ebx
  795.  
  796.         mov v_pagebase,di               ; set up and go through allocation
  797.         mov v_pagetop,di
  798.         movzx eax,di
  799.         sub eax,1000h
  800.         shl eax,10
  801.         mov ebp,ds:_code32a
  802.         sub eax,ebp
  803.         mov ds:_himembase,eax
  804.         mov ebx,8192
  805. v_startl2:
  806.         mov ax,0de04h
  807.         int 67h
  808.         or ah,ah
  809.         jnz short v_startl2d
  810.         test di,0fffh
  811.         jnz short v_startf4
  812.         add ebx,4096
  813.         cmp ebx,ebp
  814.         ja v_exiterr1
  815. v_startf4:
  816.         and dx,0f000h
  817.         or dl,7
  818.         mov es:[di],edx
  819.         add di,4
  820.         jnc v_startl2
  821. v_startl2d:
  822.         mov v_pagetop,di
  823.         lea si,[di-1000h]
  824.         movzx eax,si
  825.         shl eax,10
  826.         sub eax,ebp             ; EBP=_code32a
  827.         mov ds:_himemtop,eax
  828.         sub di,v_pagebase
  829.         cmp di,EXTMIN
  830.         mov dx,offset errmsg3
  831.         jb exit16err
  832.         add ds:_lomembase,ebx
  833.  
  834.         movzx ebx,v_pagedirseg          ; set up physical addresses
  835.         shr ebx,8
  836.         mov eax,es:[ebx*4+1000h]
  837.         mov v_ss_cr3,eax
  838.         xor di,di
  839. v_startl3:
  840.         inc ebx
  841.         mov eax,es:[ebx*4+1000h]
  842.         and ax,0f000h
  843.         or al,7
  844.         stos dword ptr es:[di]
  845.         sub si,1000h
  846.         ja v_startl3
  847.  
  848.         mov edi,offset c_startf1        ; offset to jump to in pmode
  849.         mov ebx,ds:cp_tssesp0ptr
  850.         jmp v_switchtopmode             ; duh?
  851.  
  852. ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
  853. ; 16 bit XMS system data
  854. ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
  855. x_calladdx      dd      ?               ; XMS driver addx
  856. x_handle        dw      ?               ; XMS handle of extended memory
  857. ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
  858. ; 16 bit XMS system code
  859. ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
  860. ;─────────────────────────────────────────────────────────────────────────────
  861. x_exit:                                 ; XMS exit (clean up allocation)
  862.         mov ax,cs
  863.         mov ds,ax
  864.         mov dx,x_handle
  865.         mov ah,0dh
  866.         call x_calladdx
  867.         mov ah,0ah
  868.         call x_calladdx
  869.         jmp exit
  870. ;─────────────────────────────────────────────────────────────────────────────
  871. x_exiterr5:                             ; exit with error message 5
  872.         mov dx,offset errmsg5
  873.         jmp exit16err
  874. ;═════════════════════════════════════════════════════════════════════════════
  875. x_start:                                ; start in an XMS system
  876.         or ds:_sysbyte0,1               ; set system type XMS byte
  877.  
  878.         mov ax,4310h                    ; get XMS driver addx
  879.         int 2fh
  880.         mov word ptr x_calladdx[0],bx
  881.         mov word ptr x_calladdx[2],es
  882.  
  883.         mov ah,3                        ; XMS enable A20
  884.         call x_calladdx
  885.         or ax,ax
  886.         mov dx,offset errmsg4
  887.         jz exit16err
  888.  
  889.         mov ah,8                        ; chek and get extended memory
  890.         call x_calladdx
  891.         sub ax,64
  892.         jnc short x_startf0
  893.         xor ax,ax
  894. x_startf0:
  895.         cmp ax,EXTMIN
  896.         mov dx,offset errmsg3
  897.         jb exit16err
  898.         mov dx,ax
  899.         movzx ecx,ax
  900.         shl ecx,10
  901.         mov ah,9
  902.         call x_calladdx
  903.         or ax,ax
  904.         jz x_exiterr5
  905.         mov x_handle,dx
  906.         mov exitrout,offset x_exit
  907.         mov ah,0ch
  908.         call x_calladdx
  909.         or ax,ax
  910.         jz x_exiterr5
  911.         shrd eax,edx,16
  912.         mov ax,bx
  913.         sub eax,ds:_code32a
  914.         mov ds:_himembase,eax
  915.         add eax,ecx
  916.         mov ds:_himemtop,eax
  917.  
  918.         jmp c_startf0                   ; go on to custom start
  919.  
  920. ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
  921. ; 16 bit custom system data
  922. ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
  923. c_idt16addx     dw      3ffh, 0,0       ; default real mode IDT addx&limit
  924. c_idt32addx     dw      3bfh, ?,?       ; 32bit IDT addx&limit
  925. c_gdt32addx     dw      04fh            ; 32bit GDT addx&limit
  926.                 dd      offset gdt32    ;
  927.  
  928. c_numofintvects db      77h             ; number of int vects needed -1
  929. c_idt32handler  dd      offset cp_irq0,offset cp_irq1,offset cp_irq2,offset cp_irq3
  930.                 dd      offset cp_irq4,offset cp_irq5
  931.                 dd      offset cp_irq6,offset cp_irq7,offset cp_irq8,offset cp_irq9
  932.                 dd      offset cp_irqa,offset cp_irqb
  933.                 dd      offset cp_irqc,offset cp_irqd,offset cp_irqe,offset cp_irqf
  934.                 dd      offset cp_int35,offset cp_int34,offset cp_int33,offset cp_int32,offset cp_int31
  935.                 dd      offset cp_exc0,offset cp_exc1,offset cp_exc2,offset cp_exc3
  936.                 dd      offset cp_exc4,offset cp_exc5
  937.                 dd      offset cp_exc6,offset cp_exc7,offset cp_exc8,offset cp_exc9
  938.                 dd      offset cp_exca,offset cp_excb
  939.                 dd      offset cp_excc,offset cp_excd,offset cp_exce
  940. ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
  941. ; 16 bit custom system code
  942. ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
  943. ;═════════════════════════════════════════════════════════════════════════════
  944. c_irqreal:                              ; real mode IRQ
  945.         pushf
  946.         push cs
  947.         push offset icreald2
  948.         jmp icreal
  949. ;-----------------------------------------------------------------------------
  950. c_retreal1:                             ; load some real mode stuff & exit
  951.         mov ax,codeend
  952.         mov ss,ax
  953.         mov esp,STAKLEN*10h
  954.         jmp exitrout
  955. ;═════════════════════════════════════════════════════════════════════════════
  956. c_retreal0:                             ; load real mode IDT and set PE=0
  957.         mov ax,28h
  958.         mov ds,ax
  959.         mov es,ax
  960.         mov fs,ax
  961.         mov gs,ax
  962.         mov ss,ax
  963.         lidt fword ptr c_idt16addx
  964.         mov eax,cr0
  965.         and al,0feh
  966.         mov cr0,eax
  967.         db 0eah                 ; JMP FAR PTR c_retreal0m0
  968. c_retreal0m0    dw c_sicreal,code16
  969. ;-----------------------------------------------------------------------------
  970. c_sicreal:                              ; safe real mode int or call
  971.         mov ax,codeend
  972.         mov ss,ax
  973.         mov ds,cs:v86r_ds
  974.         mov es,cs:v86r_es
  975.         db 0eah                 ; JMP FAR PTR c_sicrealm0
  976. c_sicrealm0     dw      ?,code16;
  977. ;═════════════════════════════════════════════════════════════════════════════
  978. c_retreal:                              ; return to real mode
  979.         mov c_retreal0m0,offset c_retreal1
  980.         mov esp,STAKLEN*10h
  981.         jmp c_retreal0
  982. ;═════════════════════════════════════════════════════════════════════════════
  983. c_start:                                ; custom only start
  984.         call enableA20                  ; enable that stupid A20 thingy
  985.  
  986.         mov ah,88h                      ; chek and get extended mem
  987.         int 15h
  988.         cmp ax,EXTMIN
  989.         mov dx,offset errmsg3
  990.         jb exit16err
  991.         movzx eax,ax
  992.         shl eax,10
  993.         mov ebx,100000h
  994.         sub ebx,ds:_code32a
  995.         mov ds:_himembase,ebx
  996.         add eax,ebx
  997.         mov ds:_himemtop,eax
  998. ;═════════════════════════════════════════════════════════════════════════════
  999. c_startf0:                              ; start continues from custom or XMS
  1000.         mov int32m0,CINT32              ; raw/XMS real INT32
  1001.         mov eax,2428h                   ; allocate TSS, IO bitmap, and IDT
  1002.         call pregetlomem
  1003.         mov ebx,eax
  1004.  
  1005.         lgdt fword ptr c_gdt32addx      ; switch to pmode
  1006.         mov eax,cr0
  1007.         or al,1
  1008.         mov cr0,eax
  1009.         db 0eah
  1010.         dw $+4,20h
  1011. ;-----------------------------------------------------------------------------
  1012. ; EBX->TSS
  1013. c_startf1:                              ; in 16bit pmode
  1014.         mov ax,28h                      ; set up segregs
  1015.         mov ds,ax
  1016.         mov al,18h
  1017.         mov gs,ax
  1018.         mov al,10h
  1019.         mov es,ax
  1020.         mov fs,ax
  1021.         mov ss,ax
  1022.         mov esp,STAKLEN*16
  1023.         add esp,ds:realstackbase
  1024.  
  1025.         mov word ptr v_ss_dest[4],8     ; VCPI enter 32bit pmode from now on
  1026.         lea eax,[ebx+4]                 ; addx of ESP0 in TSS
  1027.         mov ds:cp_tssesp0ptr,eax
  1028.         mov ebp,ds:_code32a             ; TSS location in mem to GDT
  1029.         lea eax,[ebx+ebp]
  1030.         mov ecx,offset ds:gdt32task     ; set up task
  1031.         or dword ptr ds:[ecx+2],eax
  1032.         mov byte ptr ds:[ecx+5],89h
  1033.         mov cx,30h
  1034.         ltr cx
  1035.         add eax,2068h                   ; set up IDT
  1036.         mov ecx,offset c_idt32addx
  1037.         mov dword ptr [ecx+2],eax
  1038.         lidt fword ptr [ecx]
  1039.  
  1040.         mov dword ptr es:[ebx+8],10h    ; set up TSS stuff (EBX->TSS)
  1041.         mov edi,104
  1042.         mov es:[ebx+102],di
  1043.         mov word ptr es:[ebx+100],0
  1044.         add edi,ebx                     ; fill IO bitmap with 0
  1045.         xor eax,eax
  1046.         mov ecx,800h
  1047.         rep stos dword ptr es:[edi]
  1048.  
  1049.         mov ds:cp_idt32ptr,edi          ; set up blank IDT entries
  1050.         movzx esi,c_numofintvects
  1051. c_startl0:
  1052.         mov dword ptr es:[edi+esi*8],80000h+offset cp_excf
  1053.         mov dword ptr es:[edi+esi*8+4],8e00h
  1054.         sub si,1
  1055.         jnc c_startl0
  1056.         mov si,23h                      ; necessary IDT entries
  1057. c_startl1:
  1058.         movzx ebp,ds:intslottbl[esi]
  1059.         mov eax,c_idt32handler[esi*4]
  1060.         cmp bp,13
  1061.         jne short c_startl1c
  1062.         mov ds:cp_int13vect,eax
  1063.         mov eax,offset cp_excd
  1064. c_startl1c:
  1065.         mov es:[edi+ebp*8],ax
  1066.         sub si,1
  1067.         jnc c_startl1
  1068.  
  1069.         mov edi,offset p_start          ; set up regs & go on to 32bit
  1070.     mov ax,10h
  1071.         mov ds,ax
  1072. ;-----------------------------------------------------------------------------
  1073. c_gotopmode:                ; jump to 32bit pmode
  1074.         pushfd                          ; set eflags: NT=0, IOPL=3
  1075.         pop eax
  1076.         and ah,0bfh
  1077.         or ah,30h
  1078.         push eax
  1079.         popfd
  1080.         dw 6866h,8,0            ; PUSH dword 8
  1081.     push edi
  1082.         db 66h,0cbh             ; 32bit RETF
  1083.  
  1084. code16  ends
  1085.  
  1086. ;▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓
  1087. ; 32bit pmode code
  1088. ;▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓
  1089. code32  segment para public use32
  1090.         assume cs:code32, ds:code32
  1091.         org 0
  1092.  
  1093. extrn   _main:near
  1094.  
  1095. public  _exit, _ret, _getmem, _getlomem, _gethimem, _lomemsize, _himemsize
  1096. public  _getirqmask, _setirqmask
  1097.  
  1098. public  v86r_eax, v86r_ebx, v86r_ecx, v86r_edx, v86r_esi, v86r_edi, v86r_ebp
  1099. public  v86r_ax, v86r_bx, v86r_cx, v86r_dx, v86r_si, v86r_di, v86r_bp
  1100. public  v86r_al, v86r_ah, v86r_bl, v86r_bh, v86r_cl, v86r_ch, v86r_dl, v86r_dh
  1101. public  v86r_ds, v86r_es, v86r_fs, v86r_gs
  1102. public  _selcode, _seldata, _selzero, _lomembase, _lomemtop, _himembase
  1103. public  _himemtop, _pspa, _code16a, _code32a, _getirqvect, _setirqvect
  1104. public  _sysbyte0, _irqmode
  1105. ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
  1106. ; 32 bit common system data
  1107. ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
  1108. _lomembase      dd      ?               ; low mem base for allocation
  1109. _lomemtop       dd      ?               ; top of low mem
  1110. _himembase      dd      0               ; high mem base for allocation
  1111. _himemtop       dd      0               ; top of high mem
  1112. _pspa           dd      ?               ; offset of start of PSP from 0
  1113. _code16a        dd      ?               ; offset of start of 16bit code from 0
  1114. _code32a        dd      ?               ; offset of start of 32bit code from 0
  1115. _selcode        dw      8               ; code segment selector
  1116. _seldata        dw      10h             ; data segment alias for code
  1117. _selzero        dw      18h             ; data segment starting at 0:0
  1118. _irqmode        dw      0ffffh          ; IRQ mode bits: 0=normal, 1=safe
  1119.                 db      0ffh            ; misc byte, has to follow _irqmode
  1120. _sysbyte0       db      0               ; system bits:
  1121.                                         ;  0-1: 0=raw, 1=XMS, 2=VCPI, 3=DPMI
  1122.  
  1123. _getirqvect     dd      cp_getirqvect   ; get IRQ handler offset routine addx
  1124. _setirqvect     dd      cp_setirqvect   ; set IRQ handler offset routine addx
  1125.  
  1126. gdt32           dq      0
  1127. gdt32code32     db      0ffh,0ffh,0,0,0,9ah,0cfh,0
  1128. gdt32data32     db      0ffh,0ffh,0,0,0,92h,0cfh,0
  1129. gdt32zero32     db      0ffh,0ffh,0,0,0,92h,0cfh,0
  1130. gdt32code16     db      0ffh,0ffh,0,0,0,9ah,0,0
  1131. gdt32data16     db      0ffh,0ffh,0,0,0,92h,0,0
  1132. gdt32task       db      0ffh,0ffh,0,0,0,89h,0,0
  1133. gdt32vcpi       dq      3 dup(?)
  1134.  
  1135. v86r_edi        label   dword           ; vregs for pmode<>real communication
  1136. v86r_di         dw      ?, ?            ;  needz to stay this way cuz its a
  1137. v86r_esi        label   dword           ;  stupid DPMI structure thingy
  1138. v86r_si         dw      ?, ?
  1139. v86r_ebp        label   dword
  1140. v86r_bp         dw      ?, ?
  1141.                 dd      0
  1142. v86r_ebx        label   dword
  1143. v86r_bx         label   word
  1144. v86r_bl         db      ?
  1145. v86r_bh         db      ?, ?,?
  1146. v86r_edx        label   dword
  1147. v86r_dx         label   word
  1148. v86r_dl         db      ?
  1149. v86r_dh         db      ?, ?,?
  1150. v86r_ecx        label   dword
  1151. v86r_cx         label   word
  1152. v86r_cl         db      ?
  1153. v86r_ch         db      ?, ?,?
  1154. v86r_eax        label   dword
  1155. v86r_ax         label   word
  1156. v86r_al         db      ?
  1157. v86r_ah         db      ?, ?,?
  1158. v86r_flags      dw      ?
  1159. v86r_es         dw      ?
  1160. v86r_ds         dw      ?
  1161. v86r_fs         dw      ?
  1162. v86r_gs         dw      ?
  1163.                 dd      0,0
  1164.  
  1165. oint1bvect      dd      ?               ; old real int 1bh vektor (ctrl+break)
  1166. oint32vect      dd      ?               ; old real int 32h vector
  1167. oirqmask        dw      ?               ; old port 21h and 0a1h masks
  1168. intslottbl      db      8,9,0ah,0bh,0ch,0dh,0eh,0fh,70h,71h,72h,73h,74h,75h,76h,77h
  1169.                 db      35h,34h,33h,32h,31h,0,1,2,3,4,5,6,7,8,9,0ah,0bh,0ch,0dh,0eh
  1170.  
  1171. code16off       dw      c_retreal       ; offset in 16bit of exit function
  1172. code16sel       dw      20h             ; 16bit pmode code selector
  1173. data16sel       dw      28h             ; 16bit pmode data selector
  1174.  
  1175. nextmodestack   dw      (STAKLEN-STAKSAFE)*16   ; stack for next mode switch
  1176. realstackbase   dd      ?               ; linear ptr to beginning of codeend
  1177.  
  1178. ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
  1179. ; 32 bit common system code
  1180. ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
  1181. ;═════════════════════════════════════════════════════════════════════════════
  1182. p_cpmode2:                ; call pmode from V86
  1183.         mov gs,cx
  1184.         mov cl,10h
  1185.         mov ds,cx
  1186.         mov es,cx
  1187.         mov fs,cx
  1188.     sub nextmodestack,STAKSAFE*16
  1189.     push p_cpmodem2
  1190.     mov p_cpmodem2,V86CPMODED
  1191.         mov eax,[esp+22]
  1192.     mov p_cpmodem0,eax
  1193.         mov al,[esp+43]
  1194.     shr al,1
  1195.     and al,1
  1196.     add al,0fah
  1197.     mov p_cpmodem1,al
  1198.         jmp short p_cpmode
  1199. ;═════════════════════════════════════════════════════════════════════════════
  1200. p_cpmode1:                              ; call pmode, load all
  1201.         mov esp,ebx
  1202.         mov ax,10h
  1203.         mov ds,ax
  1204.         mov es,ax
  1205.         mov ss,ax
  1206. ;-----------------------------------------------------------------------------
  1207. p_cpmode0:                              ; call pmode, load FS and GS
  1208.         mov fs,_seldata
  1209.         mov gs,_selzero
  1210. ;-----------------------------------------------------------------------------
  1211. p_cpmode:                               ; call pmode routine from real
  1212.         push offset p_cpmoded
  1213.         cld
  1214.         mov eax,v86r_eax
  1215.         mov ecx,v86r_ecx
  1216.         mov edx,v86r_edx
  1217.         mov ebx,v86r_ebx
  1218.         mov esi,v86r_esi
  1219.         mov edi,v86r_edi
  1220.         mov ebp,v86r_ebp
  1221.         db 68h                  ; PUSH destination address
  1222. p_cpmodem0      dd      ?       ;
  1223. p_cpmodem1      db      ?       ; CLI or STI
  1224.         ret
  1225. ;-----------------------------------------------------------------------------
  1226. p_cpmoded:                              ; call to pmode done
  1227.         cli
  1228.         pushf
  1229.         pop v86r_flags
  1230.         mov v86r_eax,eax
  1231.         mov v86r_ecx,ecx
  1232.         mov v86r_edx,edx
  1233.         mov v86r_ebx,ebx
  1234.         mov v86r_esi,esi
  1235.         mov v86r_edi,edi
  1236.         mov v86r_ebp,ebp
  1237.         mov ecx,_code16a
  1238. p_cpmodem2        label word            ; return to real, modifiable to JMP
  1239. ;-----------------------------------------------------------------------------
  1240.         movzx ebx,gs:savedstakoff[ecx]  ; DPMI return to real mode
  1241.         mov dx,gs:savedstakseg[ecx]
  1242.         mov ax,code16
  1243.         mov cx,dx
  1244.         mov si,ax
  1245.         mov edi,offset int32d0
  1246.         jmp dp_switchaddx
  1247. ;-----------------------------------------------------------------------------
  1248. VCPMODED=(($-(p_cpmodem2+2))shl 8)+0ebh
  1249. p_cpmoded2:                             ; VCPI done with pmode
  1250.         movzx esi,gs:savedstakoff[ecx]
  1251.         mov cx,code16
  1252.         mov edi,offset int32d1
  1253.         db 0eah                 ; 16bit JMP FAR 20h:v_retreal0
  1254.         dw v_retreal0,0,20h     ;
  1255. ;-----------------------------------------------------------------------------
  1256. CCPMODED=(($-(p_cpmodem2+2))shl 8)+0ebh
  1257. p_cpmoded3:                             ; raw/XMS done with pmode
  1258.         mov gs:c_retreal0m0[ecx],offset int32d3
  1259.         db 0eah                 ; 16bit JMP FAR 20h:c_retreal0
  1260.         dw c_retreal0,0,20h     ;
  1261. ;-----------------------------------------------------------------------------
  1262. if ($-(p_cpmodem2+2)) gt 127
  1263.   err
  1264. endif
  1265. V86CPMODED=(($-(p_cpmodem2+2))shl 8)+0ebh
  1266. p_cpmoded4:                ; V86 done with pmode
  1267.     pop p_cpmodem2
  1268.         jmp cp_int3_d3
  1269. ;═════════════════════════════════════════════════════════════════════════════
  1270. p_start:                                ; common 32bit start
  1271.         mov eax,gs:[1bh*4]              ; neutralize crtl+break
  1272.         mov oint1bvect,eax
  1273.         db 65h,67h,0c7h,6       ; MOV DWORD PTR GS:[1bh*4],code16:nullint
  1274.         dw 1bh*4,nullint,code16 ;
  1275.         mov eax,gs:[32h*4]              ; set up for new real mode INT32
  1276.         mov oint32vect,eax
  1277.         db 65h,67h,0c7h,6       ; MOV DWORD PTR GS:[32h*4],code16:int32
  1278.         dw 32h*4,int32,code16   ;
  1279.         in al,21h                       ; save old PIC masks
  1280.         mov ah,al
  1281.         in al,0a1h
  1282.         mov oirqmask,ax
  1283.         jmp _main                       ; go to main code
  1284.  
  1285. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  1286. ; Allocate any mem, (first cheks low, then high)
  1287. ; In:
  1288. ;   EAX - size requested
  1289. ; Out:
  1290. ;   CF=0 - memory allocated
  1291. ;   CF=1 - not enough mem
  1292. ;   EAX - linear pointer to mem or ?
  1293. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  1294. _getmem:
  1295.         push eax
  1296.         call _getlomem
  1297.         jnc short getmemd
  1298.         pop eax
  1299.         jmp short _gethimem
  1300. getmemd:
  1301.         add esp,4
  1302. _ret:                                   ; generic RET instruction
  1303.         ret
  1304. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  1305. ; Allocate some low mem
  1306. ; In:
  1307. ;   EAX - size requested
  1308. ; Out:
  1309. ;   CF=0 - memory allocated
  1310. ;   CF=1 - not enough mem
  1311. ;   EAX - linear pointer to mem or ?
  1312. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  1313. _getlomem:
  1314.         add eax,_lomembase
  1315.         cmp eax,_lomemtop
  1316.         ja short getmemerr
  1317.         xchg eax,_lomembase
  1318.         clc
  1319.         ret
  1320. getmemerr:
  1321.         stc
  1322.         ret
  1323. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  1324. ; Allocate some high mem
  1325. ; In:
  1326. ;   EAX - size requested
  1327. ; Out:
  1328. ;   CF=0 - memory allocated
  1329. ;   CF=1 - not enough mem
  1330. ;   EAX - linear pointer to mem or ?
  1331. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  1332. _gethimem:
  1333.         add eax,_himembase
  1334.         cmp eax,_himemtop
  1335.         ja short getmemerr
  1336.         xchg eax,_himembase
  1337.         clc
  1338.         ret
  1339. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  1340. ; Get amount of free low mem
  1341. ; Out:
  1342. ;   EAX - number of bytes free
  1343. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  1344. _lomemsize:
  1345.         mov eax,_lomemtop
  1346.         sub eax,_lomembase
  1347.         ret
  1348. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  1349. ; Get amount of free high mem
  1350. ; Out:
  1351. ;   EAX - number of bytes free
  1352. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  1353. _himemsize:
  1354.         mov eax,_himemtop
  1355.         sub eax,_himembase
  1356.         ret
  1357. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  1358. ; Get status of IRQ mask bit
  1359. ; In:
  1360. ;   BL - IRQ num (0-15)
  1361. ; Out:
  1362. ;   AL - status: 0=enabled, 1=disabled
  1363. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  1364. _getirqmask:
  1365.         push ax
  1366.         in al,0a1h
  1367.         mov ah,al
  1368.         in al,21h
  1369.         xchg cl,bl
  1370.         shr ax,cl
  1371.         xchg cl,bl
  1372.         and al,1
  1373.         mov [esp],al
  1374.         pop ax
  1375.         ret
  1376. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  1377. ; Set status of IRQ mask bit
  1378. ; In:
  1379. ;   BL - IRQ num (0-15)
  1380. ;   AL - status: 0=enabled, 1=disabled
  1381. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  1382. _setirqmask:
  1383.         push ax bx cx dx
  1384.         mov cl,bl
  1385.         mov bx,0fffeh
  1386.         movzx dx,al
  1387.         rol bx,cl
  1388.         shl dx,cl
  1389.         in al,0a1h
  1390.         mov ah,al
  1391.         in al,21h
  1392.         and ax,bx
  1393.         or ax,dx
  1394.         out 21h,al
  1395.         mov al,ah
  1396.         out 0a1h,al
  1397.         pop dx cx bx ax
  1398.         ret
  1399. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  1400. ; Exit to real mode
  1401. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  1402. _exit:
  1403.         cli
  1404.         mov eax,oint1bvect              ; restore ctrl+break
  1405.         mov gs:[1bh*4],eax
  1406.         mov eax,oint32vect              ; restore real mode int 32h vector
  1407.         mov gs:[32h*4],eax
  1408.         mov ax,oirqmask                 ; restore PIC masks
  1409.         out 0a1h,al
  1410.         mov al,ah
  1411.         out 21h,al
  1412.         push code16sel                  ; go to 16bit pmode exit code
  1413.         push code16off
  1414.         mov ds,data16sel
  1415.         db 66h,0cbh             ; 16bit RETF
  1416.  
  1417. ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
  1418. ; 32 bit DPMI system data
  1419. ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
  1420. dp_switchaddx   df      ?               ; switch to real mode addx
  1421. dp_saveaddx     df      ?               ; save/restore state addx
  1422. dp_savelen      dw      0,0             ; length of state buffer
  1423. dp_savedstaksel dw      ?               ; current saved stack selector
  1424.  
  1425. dp_ointbuf      df      20 dup(?)       ; saved interrupt addx buffer
  1426. ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
  1427. ; 32 bit DPMI system code
  1428. ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
  1429. ;═════════════════════════════════════════════════════════════════════════════
  1430. dp_int32:                               ; DPMI INT32/34: CX:DX=seg:off
  1431.         pushad
  1432.         shl ecx,16
  1433.         mov cx,dx
  1434.         mov bp,offset callreal
  1435.         mov dl,1
  1436.         jmp short dp_int3_
  1437. ;═════════════════════════════════════════════════════════════════════════════
  1438. dp_int33:                               ; DPMI INT33/35: AL=int num
  1439.         pushad
  1440.         movzx eax,al
  1441.         mov ecx,gs:[eax*4]
  1442.         mov bp,offset intreal
  1443.         xor dl,dl
  1444. ;-----------------------------------------------------------------------------
  1445. dp_int3_:                               ; DPMI int or call to real mode
  1446.         mov ax,900h
  1447.         int 31h
  1448.         push ax
  1449.         and al,dl
  1450.         add al,0fah
  1451.         mov ebx,_code16a
  1452.         mov gs:icrealm0[ebx],al
  1453.         mov gs:icrealm1[ebx],ecx
  1454.         push cp_savedstakoff
  1455.         push dp_savedstaksel
  1456.         movzx ebx,nextmodestack
  1457.         lea eax,[ebx-STAKSAFE*16]
  1458.         mov nextmodestack,ax
  1459.         mov ax,ss
  1460.         mov es,ax
  1461.         sub esp,dword ptr dp_savelen
  1462.         mov edi,esp
  1463.         xor al,al
  1464.         call dp_saveaddx
  1465.         mov cp_savedstakoff,esp
  1466.         mov dp_savedstaksel,ss
  1467.         mov dx,codeend
  1468.         mov ax,v86r_ds
  1469.         mov cx,v86r_es
  1470.         movzx edi,bp
  1471.         mov si,code16
  1472.         jmp dp_switchaddx
  1473. ;-----------------------------------------------------------------------------
  1474. dp_int3_d:                              ; done with real mode int or call
  1475.         mov edi,esp
  1476.         mov al,1
  1477.         call dp_saveaddx
  1478.         add esp,dword ptr dp_savelen
  1479.         pop dp_savedstaksel
  1480.         pop cp_savedstakoff
  1481.         add nextmodestack,STAKSAFE*16
  1482.         mov bx,v86r_flags
  1483.         pop ax
  1484.         int 31h
  1485.         mov ax,ds
  1486.         mov es,ax
  1487.         mov fs,ax
  1488.         mov gs,_selzero
  1489.         jmp cp_int3_d2
  1490. ;═════════════════════════════════════════════════════════════════════════════
  1491. ; DPMI IRQ redirectors (needed to make all IRQ vector selectors = CS)
  1492. dp_irq0:
  1493.         jmp cs:dp_ointbuf[0]
  1494. dp_irq1:
  1495.         jmp cs:dp_ointbuf[6]
  1496. dp_irq2:
  1497.         jmp cs:dp_ointbuf[12]
  1498. dp_irq3:
  1499.         jmp cs:dp_ointbuf[18]
  1500. dp_irq4:
  1501.         jmp cs:dp_ointbuf[24]
  1502. dp_irq5:
  1503.         jmp cs:dp_ointbuf[30]
  1504. dp_irq6:
  1505.         jmp cs:dp_ointbuf[36]
  1506. dp_irq7:
  1507.         jmp cs:dp_ointbuf[42]
  1508. dp_irq8:
  1509.         jmp cs:dp_ointbuf[48]
  1510. dp_irq9:
  1511.         jmp cs:dp_ointbuf[54]
  1512. dp_irqa:
  1513.         jmp cs:dp_ointbuf[60]
  1514. dp_irqb:
  1515.         jmp cs:dp_ointbuf[66]
  1516. dp_irqc:
  1517.         jmp cs:dp_ointbuf[72]
  1518. dp_irqd:
  1519.         jmp cs:dp_ointbuf[78]
  1520. dp_irqe:
  1521.         jmp cs:dp_ointbuf[84]
  1522. dp_irqf:
  1523.         jmp cs:dp_ointbuf[90]
  1524.  
  1525. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  1526. ; DPMI get IRQ handler offset
  1527. ; In:
  1528. ;   BL - IRQ num (0-0fh)
  1529. ; Out:
  1530. ;   EDX - offset of IRQ handler
  1531. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  1532. dp_getirqvect:
  1533.         push ax ebx cx
  1534.         movzx ebx,bl
  1535.         mov bl,intslottbl[ebx]
  1536.         mov ax,204h
  1537.         int 31h
  1538.         pop cx ebx ax
  1539.         ret
  1540. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  1541. ; DPMI set IRQ handler offset
  1542. ; In:
  1543. ;   BL - IRQ num (0-0fh)
  1544. ;   EDX - offset of IRQ handler
  1545. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  1546. dp_setirqvect:
  1547.         push ax ebx cx
  1548.         movzx ebx,bl
  1549.         mov bl,intslottbl[ebx]
  1550.         mov cx,cs
  1551.         mov ax,205h
  1552.         int 31h
  1553.         pop cx ebx ax
  1554.         ret
  1555.  
  1556. ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
  1557. ; 32 bit custom/XMS/VCPI system data
  1558. ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
  1559. vp_vcpipmentry  df      3800000000h     ; VCPI entry point in pmode
  1560.  
  1561. cp_tssesp0ptr   dd      0               ; ptr to ESP0 in TSS, or null in VCPI
  1562. cp_idt32ptr     dd      ?               ; ptr to 32bit IDT
  1563. cp_int13vect    dd      0               ; interrupt vektor 13 ptr
  1564. cp_validirqesp  dd      0               ; valid IRQ ESP value for exc 13
  1565.  
  1566. cp_v86irqintr   dd      cp_int35f1,cp_int33f0   ; IRQ int call routines
  1567. cp_v86irqnum    db      ?               ; IRQ num for V86 mode
  1568. cp_v86irqmode   db      ?               ; IRQ mode for V86 mode (safe/norm)
  1569. cp_savedstakoff dd      ?               ; current saved stack offset
  1570. ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
  1571. ; 32 bit custom/XMS/VCPI system code
  1572. ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
  1573. ;═════════════════════════════════════════════════════════════════════════════
  1574. cp_int31:                               ; INT 31h: AX=900h,901h,902h
  1575.         cmp al,1
  1576.         mov al,[esp+9]
  1577.         jb short cp_int31f0
  1578.         ja short cp_int31f1
  1579.         or byte ptr [esp+9],2
  1580.         jmp short cp_int31f1
  1581. cp_int31f0:
  1582.         and byte ptr [esp+9],0fdh
  1583. cp_int31f1:
  1584.         shr al,1
  1585.         and al,1
  1586.         iretd
  1587. ;═════════════════════════════════════════════════════════════════════════════
  1588. vp_int32:                               ; VCPI INT 32h: safe CX:DX=seg:off
  1589.         pushad
  1590.         mov ebp,offset callreal
  1591.         mov si,VICREAL1D
  1592.         mov bl,2
  1593.         jmp short cp_int34f0
  1594. ;═════════════════════════════════════════════════════════════════════════════
  1595. vp_int33:                               ; VCPI INT 33h: safe AL=int num
  1596.         pushad
  1597.         mov ebp,offset intreal
  1598. ;-----------------------------------------------------------------------------
  1599. vp_int33f0:
  1600.         mov si,VICREAL1D
  1601.         mov bl,2
  1602.         jmp short cp_int35f0
  1603. ;═════════════════════════════════════════════════════════════════════════════
  1604. cp_int32:                               ; INT 32h: safe CX:DX=seg:off
  1605.         pushad
  1606.         mov ebp,offset callreal
  1607.         mov si,CICREAL1D
  1608.         mov bl,1
  1609.         jmp short cp_int34f0
  1610. ;═════════════════════════════════════════════════════════════════════════════
  1611. cp_int33:                               ; INT 33h: safe AL=int num
  1612.         pushad
  1613.         mov ebp,offset intreal
  1614. ;-----------------------------------------------------------------------------
  1615. cp_int33f0:
  1616.         mov si,CICREAL1D
  1617.         mov bl,1
  1618.         jmp short cp_int35f0
  1619. ;═════════════════════════════════════════════════════════════════════════════
  1620. cp_int34:                               ; INT 34h: normal CX:DX=seg:off
  1621.         pushad
  1622.         mov ebp,offset callreal
  1623.         mov si,CICREAL0D
  1624.         xor bl,bl
  1625. ;-----------------------------------------------------------------------------
  1626. cp_int34f0:
  1627.         shl ecx,16
  1628.         mov cx,dx
  1629.         mov bh,1
  1630.         jmp short cp_int3_
  1631. ;═════════════════════════════════════════════════════════════════════════════
  1632. cp_int35:                               ; INT 35h: normal AL=int num
  1633.         pushad
  1634.         mov ebp,offset intreal
  1635. ;-----------------------------------------------------------------------------
  1636. cp_int35f1:
  1637.         mov si,CICREAL0D
  1638.         xor bl,bl
  1639. ;-----------------------------------------------------------------------------
  1640. cp_int35f0:
  1641.         movzx eax,al
  1642.         mov ecx,gs:[eax*4]
  1643.         xor bh,bh
  1644. ;-----------------------------------------------------------------------------
  1645. cp_int3_:                               ; int or call to real mode
  1646.         mov edi,[esp+40]
  1647.         shld eax,edi,23
  1648.         and al,bh
  1649.         add al,0fah
  1650.         mov edx,_code16a
  1651.         mov gs:icrealm0[edx],al
  1652.         mov gs:icrealm1[edx],ecx
  1653.         xchg gs:icrealm2[edx],si
  1654.         push si
  1655.         movzx esi,nextmodestack
  1656.         lea eax,[esi-STAKSAFE*16]
  1657.         mov nextmodestack,ax
  1658.         add eax,realstackbase
  1659.         mov edx,cp_tssesp0ptr
  1660.         push dword ptr [edx]
  1661.         mov [edx],eax
  1662.         sub eax,36
  1663.         push cp_validirqesp
  1664.         mov cp_validirqesp,eax
  1665.         push cp_savedstakoff
  1666.         mov cp_savedstakoff,esp
  1667.         cmp bl,1
  1668.         jb short cp_int3_n
  1669.         ja short vp_int3_s
  1670. ;-----------------------------------------------------------------------------
  1671. cp_int3_s:                              ; safe real mode int or call
  1672.         mov edx,_code16a
  1673.         mov gs:c_sicrealm0[edx],bp
  1674.         mov esp,esi
  1675.         db 0eah                 ; 16bit JMP FAR 20h:c_retreal0
  1676.         dw c_retreal0,0,20h     ;
  1677. ;-----------------------------------------------------------------------------
  1678. vp_int3_s:                              ; safe VCPI real mode int or call
  1679.         mov edi,ebp
  1680.         mov cx,v86r_ds
  1681.         mov ax,28h
  1682.         mov ds,ax
  1683.         db 0eah                 ; 16bit JMP FAR 20h:v_retreal0
  1684.         dw v_retreal0,0,20h     ;
  1685. ;-----------------------------------------------------------------------------
  1686. cp_int3_n:                              ; normal real mode int or call
  1687.         sub esp,8
  1688.         push dword ptr v86r_ds
  1689.         push dword ptr v86r_es
  1690.         db 68h                  ; 32bit PUSH codeend
  1691.         dd codeend              ;
  1692.         push esi
  1693.         or edi,20000h
  1694.         and di,0fdffh
  1695.         push edi
  1696.         db 68h                  ; 32bit PUSH code16
  1697.         dd code16               ;
  1698.         push ebp
  1699.         iretd
  1700. ;-----------------------------------------------------------------------------
  1701. cp_int3_d:                              ; done with real mode int or call
  1702.         mov ax,18h
  1703.         mov gs,ax
  1704.         mov ax,10h
  1705.         mov ds,ax
  1706.         mov es,ax
  1707.         mov fs,ax
  1708.         mov ss,ax
  1709.         mov esp,cp_savedstakoff
  1710.         pop cp_savedstakoff
  1711.         pop cp_validirqesp
  1712.         mov ebx,cp_tssesp0ptr
  1713.         pop dword ptr [ebx]
  1714.         mov ebx,_code16a
  1715.         pop gs:icrealm2[ebx]
  1716. ;-----------------------------------------------------------------------------
  1717. cp_int3_d3:                             ; done from real mode pmode call
  1718.         add nextmodestack,STAKSAFE*16
  1719.         mov bx,v86r_flags
  1720. ;-----------------------------------------------------------------------------
  1721. cp_int3_d2:                ; done from DPMI also
  1722.         mov ax,[esp+40]
  1723.         and ax,not 8d5h
  1724.         and bx,8d5h
  1725.         or ax,bx
  1726.         mov [esp+40],ax
  1727.         popad
  1728.         iretd
  1729. ;═════════════════════════════════════════════════════════════════════════════
  1730. cp_excd:                                ; general protection violation
  1731.         cmp esp,cs:cp_validirqesp       ; source an IRQ or exception¿
  1732.         jne short cp_excdf0
  1733.         jmp cs:cp_int13vect
  1734. cp_excdf0:
  1735.         test byte ptr [esp+14],2        ; exception, from V86?
  1736.         jnz short cp_excdv86
  1737.         pushad                          ; nope, pmode exception
  1738.         mov al,0dh
  1739.         jmp cp_exc
  1740. ;-----------------------------------------------------------------------------
  1741. cp_excdv86:                             ; violation from V86 mode
  1742.         add esp,4
  1743.         pushad
  1744.         mov cx,18h
  1745.         mov ds,cx
  1746.         movzx ebx,word ptr [esp+36]
  1747.         shl ebx,4
  1748.         add ebx,[esp+32]
  1749.         inc word ptr [esp+32]
  1750.         mov al,[ebx]
  1751.         mov edx,3
  1752.         cmp al,0cch
  1753.         je short cp_v86int
  1754.         mov dl,4
  1755.         cmp al,0ceh
  1756.         je short cp_v86int
  1757.         inc word ptr [esp+32]
  1758.         mov dl,[ebx+1]
  1759.         cmp dl,32h
  1760.         je p_cpmode2
  1761.         cmp dl,0ffh
  1762.         je cp_int3_d
  1763. ;-----------------------------------------------------------------------------
  1764. cp_v86int:                              ; need to simulate a real mode int
  1765.         movzx ebx,word ptr [esp+48]
  1766.         shl ebx,4
  1767.         sub word ptr [esp+44],6
  1768.         add ebx,[esp+44]
  1769.         mov ax,[esp+40]
  1770.         mov [ebx+4],ax
  1771.         and ah,0fch
  1772.         mov [esp+41],ah
  1773.         mov ax,[esp+36]
  1774.         mov [ebx+2],ax
  1775.         mov ax,[esp+32]
  1776.         mov [ebx],ax
  1777.         mov eax,[edx*4]
  1778.         mov [esp+32],ax
  1779.         shr eax,16
  1780.         mov [esp+36],ax
  1781.         popad
  1782.         iretd
  1783. ;═════════════════════════════════════════════════════════════════════════════
  1784. ; all exceptions except 0dh. all are terminal, others are redirected.
  1785. cp_exc0:
  1786.         push eax
  1787.         mov ax,1000h
  1788.         jmp cp_irq
  1789. cp_exc1:
  1790.         push eax
  1791.         mov ax,1001h
  1792.         jmp cp_irq
  1793. cp_exc2:
  1794.         push eax
  1795.         mov ax,1002h
  1796.         jmp cp_irq
  1797. cp_exc3:
  1798.         pushad
  1799.         mov al,3
  1800.         jmp short cp_exc
  1801. cp_exc4:
  1802.         pushad
  1803.         mov al,4
  1804.         jmp short cp_exc
  1805. cp_exc5:
  1806.         push eax
  1807.         mov ax,1005h
  1808.         jmp cp_irq
  1809. cp_exc6:
  1810.         pushad
  1811.         mov al,6
  1812.         jmp short cp_exc
  1813. cp_exc7:
  1814.         push eax
  1815.         mov ax,1007h
  1816.         jmp cp_irq
  1817. cp_exc8:
  1818.         pushad
  1819.         mov al,8
  1820.         jmp short cp_exc
  1821. cp_exc9:
  1822.         pushad
  1823.         mov al,9
  1824.         jmp short cp_exc
  1825. cp_exca:
  1826.         pushad
  1827.         mov al,0ah
  1828.         jmp short cp_exc
  1829. cp_excb:
  1830.         pushad
  1831.         mov al,0bh
  1832.         jmp short cp_exc
  1833. cp_excc:
  1834.         pushad
  1835.         mov al,0ch
  1836.         jmp short cp_exc
  1837. cp_exce:
  1838.         pushad
  1839.         mov al,0eh
  1840.         jmp short cp_exc
  1841. cp_excf:
  1842.         pushad
  1843.         mov al,0ffh
  1844. ;-----------------------------------------------------------------------------
  1845. cp_exc:                                 ; main exception handler
  1846.         mov ax,10h
  1847.         mov ds,ax
  1848.         mov es,ax
  1849.         mov fs,ax
  1850.         mov gs,_selzero
  1851.         cld
  1852.         jmp _exit
  1853. ;═════════════════════════════════════════════════════════════════════════════
  1854. ; IRQ redirector between modes
  1855. cp_irq0:
  1856.         push eax
  1857.         mov ax,0008h
  1858.         jmp short cp_irq
  1859. cp_irq1:
  1860.         push eax
  1861.         mov ax,0109h
  1862.         jmp short cp_irq
  1863. cp_irq2:
  1864.         push eax
  1865.         mov ax,020ah
  1866.         jmp short cp_irq
  1867. cp_irq3:
  1868.         push eax
  1869.         mov ax,030bh
  1870.         jmp short cp_irq
  1871. cp_irq4:
  1872.         push eax
  1873.         mov ax,040ch
  1874.         jmp short cp_irq
  1875. cp_irq5:
  1876.         push eax
  1877.         mov ax,050dh
  1878.         jmp short cp_irq
  1879. cp_irq6:
  1880.         push eax
  1881.         mov ax,060eh
  1882.         jmp short cp_irq
  1883. cp_irq7:
  1884.         push eax
  1885.         mov ax,070fh
  1886.         jmp short cp_irq
  1887. cp_irq8:
  1888.         push eax
  1889.         mov ax,0870h
  1890.         jmp short cp_irq
  1891. cp_irq9:
  1892.         push eax
  1893.         mov ax,0971h
  1894.         jmp short cp_irq
  1895. cp_irqa:
  1896.         push eax
  1897.         mov ax,0a72h
  1898.         jmp short cp_irq
  1899. cp_irqb:
  1900.         push eax
  1901.         mov ax,0b73h
  1902.         jmp short cp_irq
  1903. cp_irqc:
  1904.         push eax
  1905.         mov ax,0c74h
  1906.         jmp short cp_irq
  1907. cp_irqd:
  1908.         push eax
  1909.         mov ax,0d75h
  1910.         jmp short cp_irq
  1911. cp_irqe:
  1912.         push eax
  1913.         mov ax,0e76h
  1914.         jmp short cp_irq
  1915. cp_irqf:
  1916.         push eax
  1917.         mov ax,0f77h
  1918. ;─────────────────────────────────────────────────────────────────────────────
  1919. cp_irq:                                 ; main IRQ handler thingy
  1920.         mov ss:cp_v86irqnum,al
  1921.         movzx eax,ah
  1922.         bt dword ptr ss:_irqmode,eax
  1923.         setc ss:cp_v86irqmode
  1924.         pop eax
  1925.         test byte ptr [esp+10],2
  1926.         jnz short cp_irqv86
  1927.         push ds es fs gs                ; real mode IRQ from pmode
  1928.         pushfd
  1929.         push cs
  1930.         push offset cp_irqpd
  1931.         pushad
  1932.         mov ax,10h
  1933.         mov ds,ax
  1934.         mov al,18h
  1935.         mov gs,ax
  1936.         mov al,cp_v86irqnum
  1937.         mov ebp,offset c_irqreal
  1938.         movzx ebx,cp_v86irqmode
  1939.         jmp cp_v86irqintr[ebx*4]
  1940. cp_irqpd:
  1941.         pop gs fs es ds
  1942.         iretd
  1943. ;─────────────────────────────────────────────────────────────────────────────
  1944. cp_irqv86:                              ; IRQ from V86, safe or norm redirect
  1945.         cmp cs:cp_v86irqmode,0
  1946.         jne short cp_irqv86s
  1947.         pushad                          ; normal IRQ redirection
  1948.         mov ax,18h
  1949.         mov ds,ax
  1950.         movzx edx,ss:cp_v86irqnum
  1951.         jmp cp_v86int
  1952. ;-----------------------------------------------------------------------------
  1953. cp_irqv86s:                             ; safe IRQ redirection
  1954.         pushfd
  1955.         push cs
  1956.         push offset cp_irqv86sd
  1957.         pushad
  1958.         mov ax,10h
  1959.         mov ds,ax
  1960.         mov al,18h
  1961.         mov gs,ax
  1962.         sub nextmodestack,STAKSAFE*16
  1963.         mov al,cp_v86irqnum
  1964.         mov ebp,offset c_irqreal
  1965.         jmp cp_v86irqintr[4]
  1966. ;-----------------------------------------------------------------------------
  1967. cp_irqv86sd:                            ; done with safe IRQ
  1968.         add nextmodestack,STAKSAFE*16
  1969.         iretd
  1970.  
  1971. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  1972. ; Custom get IRQ handler offset
  1973. ; In:
  1974. ;   BL - IRQ num (0-0fh)
  1975. ; Out:
  1976. ;   EDX - offset of IRQ handler
  1977. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  1978. cp_getirqvect:
  1979.         push ebx
  1980.         pushf
  1981.         cli
  1982.         movzx ebx,bl
  1983.         mov bl,intslottbl[ebx]
  1984.         cmp bl,13
  1985.         je short cp_getirqvectf0
  1986.         lea ebx,[ebx*8]
  1987.         add ebx,cp_idt32ptr
  1988.         mov dx,[ebx+6]
  1989.         shl edx,16
  1990.         mov dx,[ebx]
  1991. cp_getirqvectd:
  1992.         popf
  1993.         pop ebx
  1994.         ret
  1995. cp_getirqvectf0:
  1996.         mov edx,cp_int13vect
  1997.         jmp short cp_getirqvectd
  1998. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  1999. ; Custom set IRQ handler offset
  2000. ; In:
  2001. ;   BL - IRQ num (0-0fh)
  2002. ;   EDX - offset of IRQ handler
  2003. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  2004. cp_setirqvect:
  2005.         push ebx
  2006.         pushf
  2007.         cli
  2008.         movzx ebx,bl
  2009.         mov bl,intslottbl[ebx]
  2010.         cmp bl,13
  2011.         je short cp_setirqvectf0
  2012.         lea ebx,[ebx*8]
  2013.         add ebx,cp_idt32ptr
  2014.         mov [ebx],dx
  2015.         shr edx,16
  2016.         mov [ebx+6],dx
  2017. cp_setirqvectd:
  2018.         popf
  2019.         pop ebx
  2020.         ret
  2021. cp_setirqvectf0:
  2022.         mov cp_int13vect,edx
  2023.         jmp short cp_setirqvectd
  2024.  
  2025. code32  ends
  2026.  
  2027. ;▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓
  2028. ; End of program (must be at end of program or you will suffer)
  2029. ;▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓
  2030. codeend segment para stack use32 'stack'
  2031. db STAKLEN*16 dup(?)
  2032. codeend ends
  2033.         end     start16
  2034.  
  2035.