"Fossies" - the Fresh Open Source Software Archive 
Member "fasm/source/DOS/modes.inc" (21 Feb 2022, 10419 Bytes) of package /linux/misc/fasm-1.73.30.tgz:
As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) fasm source code syntax highlighting (style:
standard) with prefixed line numbers.
Alternatively you can here
view or
download the uninterpreted source code file.
See also the latest
Fossies "Diffs" side-by-side code changes report for "modes.inc":
1.73.29_vs_1.73.30.
1
2 ; flat assembler interface for DOS
3 ; Copyright (c) 1999-2022, Tomasz Grysztar.
4 ; All rights reserved.
5
6 segment modes use16
7
8 real32:
9 mov ax,7202h
10 push ax
11 popf
12 pushf
13 pop bx
14 cmp ax,bx
15 je processor_ok
16 call init_error
17 db 'required 80386 or better',24h
18 processor_ok:
19 mov eax,ds
20 shl eax,4
21 mov [program_base],eax
22 mov eax,buffer
23 shl eax,4
24 sub eax,[program_base]
25 mov [buffer_address],eax
26
27 if UNREAL_ENABLED>0
28
29 smsw ax
30 test al,1
31 jnz dpmi
32 mov eax,cs ; calculate linear address of GDT
33 shl eax,4
34 or dword [cs:real32_GDT+10],eax
35 or dword [cs:real16_GDT+10],eax
36 add [cs:real32_GDT_address],eax
37 add [cs:real16_GDT_address],eax
38 cli
39 lgdt [cs:real32_GDTR]
40 mov eax,cr0
41 or al,1
42 mov cr0,eax
43 jmp 1 shl 3:test_pm32
44 no_rm32:
45 sti
46 jmp dpmi
47 test_pm32:
48 use32
49 mov eax,cr0
50 and al,not 1
51 mov cr0,eax
52 mov ebx,0FFFFh
53 jmp modes:test_rm32
54 test_rm32:
55 inc ebx
56 jz short no_rm32
57 lgdt [cs:real16_GDTR]
58 mov eax,cr0
59 or al,1
60 mov cr0,eax
61 jmp 1 shl 3:test_pm16
62 test_pm16:
63 use16
64 mov eax,cr0
65 and al,not 1
66 mov cr0,eax
67 jmp modes:test_rm16
68 test_rm16:
69 sti
70 mov bx,(400h+(100h*interrupt.size)) shr 4
71 mov ah,48h
72 int 21h
73 jc not_enough_memory
74 push ds es
75 mov es,ax
76 push cs
77 pop ds
78 movzx eax,ax
79 shl eax,4
80 mov [real32_IDT_base],eax
81 mov dx,100h
82 xor bx,bx
83 mov di,400h
84 init_interrupts:
85 mov si,interrupt
86 mov [si+interrupt.vector],bx
87 mov word [es:bx],di
88 mov word [es:bx+2],es
89 mov cx,interrupt.size
90 rep movsb
91 add bx,4
92 dec dx
93 jnz init_interrupts
94 pop es ds
95 call modes:switch_real32
96 use32
97 mov [mode],real32
98 retfw
99 use16
100
101 switch_real32:
102 pushfw
103 push eax
104 push word ds
105 push word es
106 push word fs
107 push word gs
108 cli
109 mov eax,ss
110 mov cr3,eax
111 lgdt [cs:real32_GDTR]
112 mov eax,cr0 ; switch to protected mode
113 or al,1
114 mov cr0,eax
115 jmp 1 shl 3:pm32_start
116 pm32_start:
117 use32
118 mov ax,2 shl 3 ; load 32-bit data descriptor
119 mov ds,ax ; to all data segment registers
120 mov es,ax
121 mov fs,ax
122 mov gs,ax
123 mov ss,ax
124 mov eax,cr0 ; switch back to real mode
125 and al,not 1
126 mov cr0,eax
127 jmp modes:pm32_end
128 pm32_end:
129 mov eax,cr3
130 mov ss,ax
131 lidt [cs:real32_IDTR]
132 pop word gs
133 pop word fs
134 pop word es
135 pop word ds
136 pop eax
137 popfw
138 retfw
139
140 switch_real16:
141 pushfw
142 push eax
143 cli
144 lgdt [cs:real16_GDTR]
145 mov eax,cr0 ; switch to protected mode
146 or al,1
147 mov cr0,eax
148 jmp 1 shl 3:pm16_start
149 pm16_start:
150 use16
151 mov eax,cr0 ; switch back to real mode
152 and al,not 1
153 mov cr0,eax
154 jmp modes:pm16_end
155 pm16_end:
156 lidt [cs:real16_IDTR]
157 pop eax
158 popfw
159 retfd
160 use32
161
162 interrupt:
163 call modes:switch_real16
164 use16
165 movzx esp,sp
166 push word [esp+4]
167 push cs
168 call .real16
169 pushfw
170 pop word [esp+4]
171 call modes:switch_real32
172 use32
173 iretw
174 .real16:
175 use16
176 push eax
177 push ds
178 xor ax,ax
179 mov ds,ax
180 mov eax,[word 0]
181 label .vector word at $-2-interrupt
182 pop ds
183 xchg eax,[esp]
184 retfw
185 .size = $-interrupt
186
187 label real32_GDTR pword
188 real32_GDT_limit dw 3*8-1 ; limit of GDT
189 real32_GDT_address dd real32_GDT ; linear address of GDT
190 real32_GDT rw 4 ; null descriptor
191 dw 0FFFFh,0,9A00h,0CFh ; 32-bit code descriptor
192 dw 0FFFFh,0,9200h,08Fh ; 4 GB data descriptor
193 label real16_GDTR pword
194 real16_GDT_limit dw 2*8-1 ; limit of GDT
195 real16_GDT_address dd real16_GDT ; linear address of GDT
196 real16_GDT rw 4 ; null descriptor
197 dw 0FFFFh,0,9A00h,0 ; 16-bit code descriptor
198
199 label real32_IDTR pword
200 real32_IDT_limit dw 3FFh
201 real32_IDT_base dd ?
202 label real16_IDTR pword
203 real16_IDT_limit dw 3FFh
204 real16_IDT_base dd 0
205
206 end if
207
208 dpmi:
209 mov ax,1687h
210 int 2Fh
211 or ax,ax ; DPMI installed?
212 jnz no_dpmi
213 test bl,1 ; 32-bit programs supported?
214 jz no_dpmi
215 mov word [cs:mode_switch],di
216 mov word [cs:mode_switch+2],es
217 mov bx,si ; allocate memory for DPMI data
218 mov ah,48h
219 int 21h
220 jc not_enough_memory
221 mov ds,[environment_segment]
222 mov es,ax
223 mov ax,1
224 call far [cs:mode_switch] ; switch to protected mode
225 jc no_dpmi
226 mov cx,1
227 xor ax,ax
228 int 31h ; allocate descriptor for code
229 mov si,ax
230 xor ax,ax
231 int 31h ; allocate descriptor for data
232 mov di,ax
233 mov dx,cs
234 lar cx,dx
235 shr cx,8
236 or cx,0C000h
237 mov bx,si
238 mov ax,9
239 int 31h ; set code descriptor access rights
240 mov dx,ds
241 lar cx,dx
242 shr cx,8
243 or cx,0C000h
244 mov bx,di
245 int 31h ; set data descriptor access rights
246 mov ecx,main
247 shl ecx,4
248 mov dx,cx
249 shr ecx,16
250 mov ax,7
251 int 31h ; set data descriptor base address
252 movzx ecx,word [esp+2]
253 shl ecx,4
254 mov dx,cx
255 shr ecx,16
256 mov bx,si
257 int 31h ; set code descriptor base address
258 mov cx,0FFFFh
259 mov dx,0FFFFh
260 mov ax,8 ; set segment limit to 4 GB
261 int 31h
262 mov bx,di
263 int 31h
264 mov ax,ds
265 mov ds,di
266 mov [psp_segment],es
267 mov [environment_segment],ax
268 mov es,di
269 mov [mode],dpmi
270 pop ebx
271 movzx ebx,bx
272 push esi
273 push ebx
274 retfd
275
276 init_error:
277 push cs
278 pop ds
279 mov dx,init_error_prefix
280 mov ah,9
281 int 21h
282 pop dx
283 int 21h
284 mov dx,init_error_suffix
285 int 21h
286 mov ax,04CFFh
287 int 21h
288
289 init_error_prefix db 0Dh,0Ah,'error: ',24h
290 init_error_suffix db '.',0Dh,0Ah,24h
291
292 mode_switch dd ?
293
294 not_enough_memory:
295 call init_error
296 db 'not enough conventional memory',24h
297
298 if UNREAL_ENABLED>0
299
300 no_dpmi:
301 smsw ax
302 test al,1
303 jz no_real32
304 call init_error
305 db 'system is in protected mode without 32-bit DPMI services',24h
306 no_real32:
307 call init_error
308 db 'processor is not able to enter 32-bit real mode',24h
309
310 else
311
312 no_dpmi:
313 call init_error
314 db 'no 32-bit DPMI services are available',24h
315
316 end if
317
318 use32
319
320 if UNREAL_ENABLED>0
321
322 init_real32_memory:
323 mov ax,4300h ; check for XMS
324 int 2Fh
325 cmp al,80h ; XMS present?
326 je xms_init
327 mov ax,0E801h ; check for large free extended memory
328 int 15h
329 jnc large_raw_memory
330 mov ah,88h ; how much extended memory free?
331 int 15h
332 or ax,ax
333 jz no_extended_memory
334 movzx eax,ax ; convert AX kilobytes to pointer
335 shl eax,10
336 jmp use_raw_memory
337 large_raw_memory:
338 movzx ecx,cx
339 shl ecx,10
340 movzx edx,dx
341 shl edx,16
342 mov eax,ecx
343 add eax,edx
344 use_raw_memory:
345 add eax,100000h
346 sub eax,[program_base]
347 mov [memory_end],eax
348 push ds
349 push 0 ; DS := 0
350 pop ds
351 call enable_a20 ; enable A20
352 call test_a20 ; is A20 enabled?
353 jz a20_ok
354 pop ds
355 jmp no_extended_memory
356 a20_ok:
357 lds bx,dword [4*19h]
358 mov eax,100000h ; initial free extended memory base
359 cmp dword [bx+12h],'VDIS' ; VDISK memory allocation?
360 jne short no_vdisk ; if present, get base of free memory
361 mov eax,dword [bx+2Ch] ; get first free extended memory byte
362 add eax,0Fh ; align on paragraph
363 and eax,0FFFFF0h ; address is only 24bit
364 no_vdisk:
365 push 0FFFFh ; DS := FFFFh for ext mem addressing
366 pop ds
367 cmp dword [13h],'VDIS' ; VDISK memory allocation?
368 jne short vdisk_ok ; if present, get base of free memory
369 movzx ebx,word [2Eh] ; get first free kilobyte
370 shl ebx,10
371 cmp eax,ebx ; pick larger of 2 addresses
372 ja short vdisk_ok
373 mov eax,ebx
374 vdisk_ok:
375 pop ds
376 sub eax,[program_base]
377 mov [memory_start],eax
378 mov edx,[memory_setting]
379 shl edx,10
380 jz extended_memory_ok
381 mov eax,[memory_end]
382 sub eax,[memory_start]
383 sub eax,edx
384 jbe extended_memory_ok
385 sub [memory_end],eax
386 jmp extended_memory_ok
387 enable_a20:
388 call test_a20 ; is A20 already enabled?
389 jz a20_enabled ; if yes, done
390 in al,92h ; PS/2 A20 enable
391 or al,2
392 out 92h,al
393 call test_a20 ; is A20 enabled?
394 jz a20_enabled ; if yes, done
395 call kb_wait ; AT A20 enable
396 jnz a20_enabled
397 mov al,0D1h
398 out 64h,al
399 call kb_wait
400 jnz a20_enabled
401 mov al,0DFh
402 out 60h,al
403 call kb_wait
404 a20_enabled:
405 retn
406 kb_wait: ; wait for safe to write to 8042
407 xor cx,cx
408 .loop:
409 in al,64h ; read 8042 status
410 test al,2 ; buffer full?
411 loopnz .loop ; if yes, loop
412 retn
413 test_a20: ; test for enabled A20
414 mov al,[0] ; get byte from 0:0
415 mov ah,al ; preserve old byte
416 not al ; modify byte
417 xchg al,[100000h] ; put modified byte to 0FFFFh:10h
418 cmp ah,[0] ; set zero if byte at 0:0 not modified
419 mov [100000h],al ; restore byte at 0FFFFh:10h
420 retn ; return, zero if A20 enabled
421 xms_init:
422 push es
423 mov ax,4310h ; get XMS driver address
424 int 2Fh
425 mov word [cs:xms_proc],bx ; store XMS driver address
426 mov word [cs:xms_proc+2],es
427 pop es
428 mov ah,3 ; enable A20
429 call call_xms
430 cmp ax,1 ; error enabling A20?
431 jne no_extended_memory
432 mov ah,88h ; get free extended memory size (XMS 3.0)
433 xor bl,bl
434 call call_xms
435 or bl,bl
436 jz xms_large_init
437 mov ah,8 ; get free extended memory size
438 xor bl,bl
439 call call_xms
440 or bl,bl
441 jnz no_extended_memory
442 mov dx,ax
443 movzx eax,ax
444 shl eax,10
445 mov [memory_end],eax
446 mov ah,9 ; allocate largest memory block
447 xms_allocate:
448 mov ecx,[memory_setting]
449 shl ecx,10
450 jz xms_size_ok
451 cmp ecx,[memory_end]
452 jae xms_size_ok
453 mov [memory_end],ecx
454 mov edx,[memory_setting]
455 xms_size_ok:
456 call call_xms
457 mov [cs:xms_handle],dx
458 cmp ax,1
459 jne no_extended_memory
460 mov ah,0Ch ; lock extended memory block
461 call call_xms
462 cmp ax,1
463 jne no_extended_memory
464 shl edx,16
465 mov dx,bx
466 sub edx,[program_base]
467 mov [memory_start],edx ; store memory block address
468 add [memory_end],edx
469 jmp extended_memory_ok
470 xms_large_init:
471 mov edx,eax
472 shl eax,10
473 mov [memory_end],eax
474 mov ah,89h ; allocate largest memory block (XMS 3.0)
475 jmp xms_allocate
476 call_xms:
477 call modes:switch_real16
478 use16
479 call far dword [cs:xms_proc]
480 call modes:switch_real32
481 use32
482 retn
483 no_extended_memory:
484 xor eax,eax
485 mov [memory_start],eax
486 extended_memory_ok:
487 mov ah,48h ; get free conventional memory size
488 mov bx,-1
489 int 21h
490 movzx ecx,bx
491 shl ecx,4
492 mov ah,48h ; allocate all conventional memory
493 int 21h
494 movzx edi,ax
495 shl edi,4
496 sub edi,[program_base]
497 mov [additional_memory],edi
498 mov [additional_memory_end],edi
499 add [additional_memory_end],ecx
500 cmp [memory_start],0
501 je only_conventional_memory
502 mov eax,[memory_end]
503 sub eax,[memory_start]
504 shr eax,2
505 cmp eax,ecx
506 jbe real32_memory_ok
507 mov eax,[memory_end]
508 mov ebx,[memory_start]
509 sub eax,ebx
510 shr eax,2
511 mov [additional_memory],ebx
512 add ebx,eax
513 mov [additional_memory_end],ebx
514 mov [memory_start],ebx
515 real32_memory_ok:
516 retf
517 only_conventional_memory:
518 shr ecx,2 ; use part of conventional memory
519 add edi,ecx ; as a substitute for extended memory
520 mov [memory_start],edi
521 xchg [additional_memory_end],edi
522 mov [memory_end],edi
523 retf
524
525 free_real32_memory:
526 cmp [cs:xms_handle],0
527 je no_xms
528 mov ah,0Dh ; unlock extended memory block
529 mov dx,[cs:xms_handle]
530 call call_xms
531 mov ah,0Ah ; free extended memory block
532 call call_xms
533 no_xms:
534 retf
535
536 xms_proc dd ? ; XMS driver pointer
537 xms_handle dw ? ; handle of XMS memory block
538
539 end if