]> 4ch.mooo.com Git - 16.git/blob - src/lib/doslib/hw/cpu/protdpmi.asm
added a bunch of things~ and midi stuff~
[16.git] / src / lib / doslib / hw / cpu / protdpmi.asm
1 ; protdpmi.asm
2 ;
3 ; Test program: Protected mode via DPMI (DOS Protected Mode Interface)
4 ; (C) 2010-2012 Jonathan Campbell.
5 ; Hackipedia DOS library.
6 ;
7 ; This code is licensed under the LGPL.
8 ; <insert LGPL legal text here>
9 ;
10 ; proot of concept:
11 ; switching the CPU into 386 16-bit protected mode (and back) using DPMI
12 bits 16                 ; 16-bit real mode
13 org 0x100               ; MS-DOS .COM style
14
15 ; assume ES == DS and SS == DS and DS == CS
16
17 ; ===== ENTRY POINT
18                 mov             ax,cs
19                 mov             ds,ax
20                 mov             es,ax
21                 mov             ss,ax
22
23 ; we need to use DOS memory allocation, so we first need to resize our
24 ; memory ownership down to the actual size of the COM file.
25 ; Windows NT/XP/etc. seem to assume the COM takes 64KB, while Windows 95
26 ; follows the DOS way and has the COM assume all memory. So for this
27 ; code to work under Win9x much less DOS we need to do this step.
28                 mov             ah,0x4A         ; INT 21h AH=4Ah resize memory block
29                 mov             bx,cs
30                 mov             es,bx           ; ES=our PSP segment
31                 mov             bx,ENDOI
32                 shr             bx,4            ; in paragraphs, the size of this program + data
33                 int             21h
34
35                 mov             [MY_SEGMENT],ax
36                 mov             bx,ax
37                 shr             bx,12
38                 shl             ax,4
39                 mov             [MY_PHYS_BASE+2],bx
40                 mov             [MY_PHYS_BASE+0],ax
41
42                 mov             ax,0x1687
43                 int             2Fh
44                 or              ax,ax
45                 jz              dpmi_present
46                 mov             dx,str_cpu_need_dpmi
47                 jmp             exit2dos_with_message
48 dpmi_present:
49                 mov             [dpmi_entry+0],di
50                 mov             [dpmi_entry+2],es
51                 mov             [dpmi_data_size],si
52
53 ; allocate private data for DPMI server, if needed
54                 mov             word [dpmi_data_seg],0
55                 cmp             word [dpmi_data_size],0
56                 jz              dpmi_no_private
57                 mov             ah,0x48
58                 mov             bx,[dpmi_data_size]     ; in paragraphs
59                 int             21h
60                 jnc             .allocd
61                 mov             dx,str_cpu_dpmi_private_alloc_fail
62                 jmp             exit2dos_with_message
63 .allocd:        mov             [dpmi_data_seg],ax
64 dpmi_no_private:
65 ; at this point: either we allocated memory successfully, or the DPMI server does not need private data segment
66 ; make the jump
67                 mov             es,[dpmi_data_seg]
68                 mov             ax,1            ; 16-bit app
69                 call far        word [dpmi_entry]
70                 jnc             dpmi_ok
71                 mov             dx,str_dpmi_entry_fail
72                 jmp             exit2dos_with_message
73 dpmi_ok:
74 ; save our protected mode side
75                 mov             ax,cs
76                 mov             [MY_CODE_SEL],ax
77                 mov             ax,ds
78                 mov             [MY_DATA_SEL],ax
79
80 ; we need a selector to draw on the screen with
81                 mov             ax,0x0002
82                 mov             bx,0xB800
83                 int             31h
84                 mov             [vga_sel],ax
85
86 ; draw on the screen
87                 mov             si,vdraw_msg
88                 xor             di,di
89                 call            vga_puts
90
91 ; now switch back to real mode
92                 mov             ax,0x0306
93                 int             31h
94                 mov             [raw_entry],cx
95                 mov             [raw_entry+2],bx
96                 mov             [raw_exit],edi
97                 mov             [raw_exit+4],si
98
99 ; switch
100                 mov             ax,[MY_SEGMENT] ; AX will become DS
101                 mov             cx,ax           ; CX will become ES
102                 mov             dx,ax           ; DX will become SS
103                 movzx           ebx,sp          ; EBX will become (E)SP
104                 mov             si,ax           ; SI will become CS
105                 mov             edi,.realmode
106                 jmp far         dword [raw_exit]
107 .realmode:
108
109 ; we made it!
110                 mov             si,vdraw2_msg
111                 mov             di,80*2
112                 call            vga_puts_real
113
114 ; jump back to protected mode
115                 mov             ax,[MY_DATA_SEL]        ; AX will become DS
116                 mov             cx,ax                   ; CX will become ES
117                 mov             dx,ax                   ; DX will become SS
118                 movzx           ebx,sp                  ; EBX will become (E)SP
119                 mov             si,[MY_CODE_SEL]        ; SI will become CS
120                 mov             edi,.protagain
121                 jmp far         word [raw_entry]
122 .protagain:
123
124 ; we made it!
125                 mov             si,vdraw3_msg
126                 mov             di,80*2*2
127                 call            vga_puts
128
129 ; ===== DONE
130                 jmp             exit2dos
131
132 ; ===== EXIT TO DOS WITH ERROR MESSAGE DS:DX
133 exit2dos_with_message:
134                 mov             ah,9
135                 int             21h
136 ; ===== EXIT TO DOS
137 exit2dos:       mov             ax,4C00h
138                 int             21h
139
140 vga_puts_real:
141 ; DS:SI = what to put
142 ;    DI = where to put it
143                 push            es
144                 push            ax
145                 push            si
146                 push            di
147                 cld
148                 mov             ax,0xB800
149                 mov             es,ax
150 .l1:            lodsb
151                 or              al,al
152                 jz              .le
153                 mov             ah,0x1E
154                 stosw
155                 jmp             .l1
156 .le:            pop             di
157                 pop             si
158                 pop             ax
159                 pop             es
160                 ret
161
162 vga_puts:
163 ; DS:SI = what to put
164 ;    DI = where to put it
165                 push            es
166                 push            ax
167                 push            si
168                 push            di
169                 cld
170                 mov             ax,[vga_sel]
171                 mov             es,ax
172 .l1:            lodsb
173                 or              al,al
174                 jz              .le
175                 mov             ah,0x1E
176                 stosw
177                 jmp             .l1
178 .le:            pop             di
179                 pop             si
180                 pop             ax
181                 pop             es
182                 ret
183
184 ; strings
185 str_cpu_need_dpmi:db            "DPMI server required$"
186 str_cpu_dpmi_private_alloc_fail:db "Unable to allocate private data for DPMI$"
187 str_dpmi_entry_fail:db          "Unable to enter DPMI protected mode$"
188 vdraw_msg:      db              "This message was drawn on screen from DPMI 16-bit protected mode!",0
189 vdraw3_msg:     db              "This message was drawn on screen back into DPMI 16-bit protected mode!",0
190 vdraw2_msg:     db              "This message was drawn on screen back from real mode!",0
191
192 ; vars
193                 section         .bss align=8
194 dpmi_entry:     resd            1
195 raw_entry:      resd            1
196 raw_exit:       resd            1
197                 resw            1
198 dpmi_data_size: resw            1
199 dpmi_data_seg:  resw            1
200 MY_PHYS_BASE:   resd            1
201 MY_CODE_SEL:    resw            1
202 MY_DATA_SEL:    resw            1
203 MY_SEGMENT:     resd            1
204 vga_sel:        resw            1
205 ENDOI:          resb            1
206