"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