
              
                           
              :                  :      
                                  |
                              Ŀ
                   FLAT AL MOD DOS-XTD 
        |                                             
        :                y CHSTOPH AVO 95-96 |
                                                                    :
                              VSION 1.0 

Ŀ
                          Ŀ                          
              Ĵ iF R M 3 2 . T X T Ŀ              
Ĵ                      
                               Version 1.00                
                                                           
                 DOCUMENTATION SUR LE DOS-EXTENDER iFM32  
                 
                   (C) Christophe AVOINNE, 1995 - 1996     
               

     

  Contenu:
   
	 iFM32.TXT   Ce fichier
	 iFM32.ASM   Fichier-source du DOS-extender iFM32
	 iFM32.ASI
	 iFM32.EXE   Fichier-excutable du DOS-extender iFM32
   SERVICES.TXT Documentation sur les services offerts par iFM32
  
     
  
  Caractristiques gnrales:
   
   Le fichier iFRM32.EXE est  utilisable pour toutes applications s'excu-
    tant en code 32-bit dans le mode rel plat.                            
   Ne peut  tre  utilis  qu'en mode rel, non en mode virtuel ni en mode
    protg (Windows, VCPI et DPMI);  un  gestionnaire EMM386 ou compatible
    ne doit pas tre charg.                                               
   Les applications  iFM32  accdent  pleinement  au BIOS  et  au DOS  en
    utilisant  les mme conventions d'appel  au BIOS  et  au DOS ( INT xx )
    que les applications DOS normaux,   quelques exceptions prs : la pile
    du code 32-bit se doit d'tre en 16-bit pour tous les passages de para-
    mtres par la pile ( rares sont les interruptions qui en font usage ).   
   Les sources C  peuvent tre utiliss avec iFM32,  sous rserve d'avoir
    un compilateur C 32-bit en main et d'apporter  quelques modifications 
    aux sources obtenus en assembleur.                                     
	 A l'inverse de bien d'autres DOS extenders,  la problmatique de la r-
	  entrance NE se pose PAS sous iFM32. Elle ne sera donc discute dans ce
	  fichier.                            

     

  Historique:
   
  
  1) Pourquoi iFM32 ?

   Certaines personnes  soutenaient   tort  que  les "DOS Extender 32-bit"
  en mode protg  fussent  le seul moyen possible  pour  excuter  un code
  32-bit dans un modle de mmoire  plat . Il tait rageant d'entendre de
  pareils propos,  alors mme  qu'aucun  n'tait  mme de le prouver. Bien
  que j'eus par moment douter, j'ai  toujours cru  la possibilit de crer
  un vrai  DOS Extender 32-bit  en mode rel. Voil pourquoi iFM32 a t
  conu au dpart.                             

  Le mode virtuel est, par nature, lent.  trs lent, mme : l'excution des
  interruptions en mode virtuel provoquent un retour oblig en mode protg
  pour repasser  en mode virtuel  par le biais d'un moniteur virtuel. Cette
  opration  est  trs coteuse en cycles - et, pour ma part, mal tudie -
  pour les IRQ! Pis, tous les INT imbriqus les uns dans les autres doivent
  tre muls  par  le moniteur  dans la famille des 386 et 486. Certes, le
  mode virtuel offre l'avantage non-ngligeable de la pagination. Mais tous
  les DOS extenders 32-bit ne l'offrent pas systmatiquement.
  
  Le multi-tche ?  honntement, si  une  application  iFM32  a rellement
  besoin de puissance et de ressources  et  qu'elle  n'est  pas  destine 
  tourner dans un contexte multi-tche,  cela ne ferait que de la ralentir.

  En outre, pour que le multi-tche ft efficace, il aurait fallu imprati-
  vement passer par la pagination,  ce que  le mode rel  ne peut hlas pas
  offrir, du moins avec les pentiums ( l'instruction non-documente LOADALL
  n'est en effet plus disponible  partir des pentiums,  et de toute faon,
  cette instruction est extrmement mal habile  utiliser ).

  Autre fait  qui  empche  d'opter  pour le mode virtuel : l'impossibilit
  d'aggrandir les limites des segments   4 Go  ou mme  de passer  du code
  16-bit en 32-bit et vice versa sous le mode virtuel ( le microprocesseur,
  juste avant de passer en mode virtuel  via " iretd " se charge de redfi-
  nir les limites, les bases, etc. de tous les registres de segment,  et ce
  sans passer par la GDT!  cela  signifie des segments avec, dsesprement,
  64 Ko en limite,  et un DPL gale  trois  qui empche toute tentative de
  redfinir ces registres ).
  
  Or prcisement,  un  certain  nombre de DOS-extenders  n'utilisent pas la
  pagination : alors, pourquoi en mode protg? surtout, si un DOS-extender
  32-bit en mode rel  peut se rvler justement plus rapide  et  plus ais
   l'utilisation que la plupart des DOS-extenders "traditionnels".
  
  Par la  suite,  iFM32  a  t  conu  pour permettre    n'importe  quel
  programmeur  habitu au DOS et au BIOS, de pourvoir crire ses programmes
  et de les excuter  dans le code souhait,  et  de lui  permettre l'accs
   l'espace de mmoire tout entier du PC (4 Go au maximum),  plus aisement
  qu'il  ne  l'aurait fait  en mode protg  ( problme de conversion entre
  slecteur et segment, par exemple ).

  2) Qu'est-ce iFM32 ?

  iFM32  signifie  " INTEL FLAT REAL MODE 32-BIT ",  et  il est conu pour                       
  pouvoir  excuter  des  code 32-bit  en mode rel,  tout  en assurant une                       
  compatibilit la meilleure que possible avec le DOS et le BIOS du PC.                          
                                                                                               
  Il se prsente  sous  la  forme  d'un  fichier-excutable que  l'on peut                       
  installer aprs HIMEM.SYS  dans  CONFIG.SYS ( INSTALL= <..>\iFRM32.EXE )                       
  ou l'appeler  sous  DOS  pour l'installer et l'activer soit en rsident,
  soit le temps d'excuter une application iFM32.
  
     

  Comment utiliser iFM32 ?
   
	 L'accs aux fonctionnalits de iFM32  s'effectue  travers les inter-
	  ruptions 2Fh, A8h-B3h :

                                                                          
    - int 2Fh, AX = 43FFh: uniquement utilisable  en  code 16-bit, atteste
    de la prsence de iFM32  en  envoyant  6945524Dh  " iFRM "  dans EAX,
    " 32C " dans EDX et dans le couple ES:EBX  un  pointeur  sur la table
    suivante, aprs initialisation de l'iFM32 : 
                                                                          
          ATTENTION : cet appel doit se faire avant tout autre appel       
          des interruptions de iFM32 !
          
    NOTE : vitez d'utiliser au possible cette table directement, elle est
    encore accessible  uniquement  pour des raisons  de compatibilit avec
    les  anciennes  applications d'iFM32  et priviligiez les appels aux
    fonctions de services offert par iFM32 via l'interruption 0B0h !
                                                                          
     ͻ
      Adresse  Contenu                                         Type   
     ͹
      + 0000h  Attribut/tat du gestionnaire:                4 BYTES  
               - bit 31:  un si prsent;                             
               - bit 30:  un  si  un  gestionnaire XMM est           
                 prsent (HIMEM.SYS);                                 
               - bit 29:  un si la ligne d'adresse A20 n'a           
                 pas pu tre libre;                                 
               - les autres bits sont rservs.         !!!           
     Ķ
      + 0004h  Nombre d'applications iFRM32 en cours    !!!  1 DWORD  
     Ķ
      + 0008h  Numro de version                        !!!  1 WORD   
     Ķ
      + 000Ah  Taille de la GDT, utilise par iFM32    !!!  1 WORD*  
     Ķ
      + 000Ch  Adresse linaire de base de la GDT****   !!!  1 DWORD* 
     Ķ
      + 0010h  Taille de la IDT16, utilise par iFM32:      1 WORD*  
               la IDT16 est la table d'interruptions 16-bit           
     Ķ
      + 0012h  Adresse physique de base de la IDT16***       1 DWORD* 
     Ķ
      + 0016h  Taille de la IDT32, utilise par iFM32:      1 WORD*  
               la IDT32 est la table d'interruptions 32-bit           
     Ķ
      + 0018h  Adresse physique de base de la IDT32***       1 DWORD* 
     Ķ
      + 001Ch  Addresse logique de la pile 16-bit            2 DWORD**
     Ķ
      + 0024h  Addresse logique de la pile 32-bit            2 DWORD**
     Ķ
        ...                        ...                         ...    
     ͼ
                                                            
  !!! N'Y TOUCHEZ PAS SANS RAISON PARTICULIERE !
                                                                          
    *  ne manipuler qu'avec prcaution par des programmeurs avertis!     
   ** le premier double-mot dsigne un offset 32-bit, le second un segment
  *** il s'agit des IDTP 16-bit et 32-bit  qu'iFM32  utilise pour pointer
      sur la bonne table des interruptions                                
 **** il s'agit de la GDT qu'iFM32 utilise pour initialiser les registres
      de segments; N'Y TOUCHEZ PAS SANS RAISON PARTICULIERE !              
                                                                          
     - int 0A8h , "CS16" : passe en code 16-bit si et seulement si le code
     en cours est un code 32-bit.                                         
                                                                          
     - int 0A9h , "CS32" : passe en code 32-bit si et seulement si le code
     en cours est un code 16-bit.                                         
                                                                          
     - int 0AAh~0ABh : RESERVEES, ne pas y toucher!                                     
                                                                          
     - int 0ACh , "SS16" : utilise la pile 16-bit pour le code en cours. 
                                                                          
     - int 0ADh , "SS32" : utilise la pile 32-bit pour le code en cours.  
                                                                          
     - int 0AEh~0AFh: RESERVEES, ne pas y toucher!                        
                                                                          
     - int 0B0h: services divers qu'offre iFM32.                         
       voir le fichier SERVICES.TXT pour de plus amples dtails.

     - int 0B1h: initialise une zone de mmoire pour le prparer
        hberger un tas ( gestion de mmoire dynamique ).
       Entre:
         ds:eax = adresse de base de la zone.
         ecx = taille en octet de la zone ( multiple de 32 octets).
       Sortie:
         ds:ebx = adresse qui dtermine le tas cre dans la zone.
                           
		 - int 0B2h: alloue un bloc dans un tas spcifi.
       Entre:
         ds:ebx = adresse du tas spcifi.
         eax = taille en octet du bloc.
       Sortie:
       si cf = 0,
         ds:eax = adresse qui dtermine le tas cre dans la zone.
		 
		 - int 0B3h: libre un bloc dans un tas spcifi.
       Entre:
         ds:ebx = adresse du tas spcifi.
         eax = adresse du bloc.
       Sortie:
       si cf = 0, ok.
     
       
     

  Description et techniques:
   

   a) Ce qu'il faut savoir:                                                 
                                                                          
      Le registre de segment CS  contient  dans  sa  partie invisible, des
      informations sur  son  adresse linaire de base, sa limite, son type
      et niveau de privilge ( ici, toujours code non-conforme, lisible et
      de niveau de privilge 0 - i.e, aucune restriction sur l'utilisation
      de certaines instructions - ET, bien sr,  le bit D qui indique s'il
      faut excuter par dfaut le code comme un 16-bit - D=0 - ou comme un
      32-bit - D=1 ).  A l'initialisation de iFM32, la limite de tous les
      registres de segment est tendue  4 Go,  pour permettre l'accs via
      ces registres  dans  tout  l'espace physique  de  l'ordinateur, lors
      des rfrence-mmoires.  C'est  donc  en  manipulant ce bit D, qu'on
      parvient  excuter un code 32-bit en mode rel.                    
                                                                          
      Par ailleurs,  l'excution des bonnes interruptions selon le code en
      cours est due au registre IDTR,  qui permet de pointer sur une table
      d'interruption compatible  avec  le  code en cours; le changement de
      table s'effectue avec le chargement du registre IDTR, " lidt ",  qui
      ne prend qu'une dizaine de cycles: qui a dit que le mode rel n'uti-
      lisait pas l'IDTR, pour accder aux vecteurs des interruptions?     
                                                                          

   b) Les interruptions avec iFM32:                                        
                                                                          
      iFM32 offre trois tables  de vecteurs d'interruption  selon le mode
      du code en vigueur:                                                    
      - deux 16-bit : c'est celui  qu'en fait offrent le BIOS et le DOS en
      temps normal;  l'une  peut  servir  pour  muler  des  interruptions
      16-bits qui ont besoin d'une pile 16-bit  ( DOS et BIOS ) lorsque le
      code 16-bit utilise par dfaut une pile 32-bit.
      - une 32-bit : c'est une autre table qui mule les interruptions in-
      ternes  ( DOS, BIOS, par exemple )  et les IRQ.                                
                                                                          
      Les entres  de ces tables  peuvent  tre  dtournes aux profits de
      "handlers"  propres  aux  programmeurs  d'applications  iFM32. Mais
      attention,  si ces "handlers"  doivent pouvoir s'excuter aussi bien
      en code 16-bit qu'en 32-bit,  il faut modifier les deux entres dans
      les deux tables,  en particulier  si ce sont des IRQ.  Et  dans  les
      trois tables, si on autorise au code 16-bit l'accs  la pile 32-bit
      dans certains cas.              
                                                                          
      Voici  comment  faire,  par  exemple  pour  installer  un  "handler"
      IRQ 32-bit ( ici, le  TIMER  ), dans un segment 32-bit :           
                                                                          
        NOTE : le code 16-bit n'a pas accs  la pile 32-bit, donc deux
        tables suffisent.                                                                  
                                                                          
      ...                                                                 
      IRQ816:    int    0A9h    ; passe en code 32-bit                  
                   call   IRQ8                                           
                   int    0A8h    ; passe en code 16-bit                  
                   iretw          ; excute un iret 16-bit              
      IRQ832:    call   IRQ8                                           
                   iretw          ; excute un iret 16-bit
                                  ; mme sous un code 32-bit                                        
      IRQ8:       ...            ; le "handler" IRQ en 32-bit            
                   retn                                                   
      ...                                                                 
                                                                          
      o: IRQ816  est le vecteur  pour la table 16-bit, et IRQ832 pour
          la table 32-bit.                                                
                                                                          
      ...                                                                 
      installourhandlers:
                   ; \\ la sous-fonction 6 se sert de la valeur de DS
                   ; \\ en entre pour calculer les offsets de ESI et
                   ; \\ EDI en sortie ( adresses des tables ).                                                     
                   mov    ah,6             ;  GET IDT                   
                   int    0B0h             ; iFM32 service               
                   mov    eax,cs                                          
                   shl    eax,16                                          
                   mov    edx,eax                                         
                   mov    ax,SMALL OFFSET IRQ816                        
                   mov    dx,SMALL OFFSET IRQ832                        
                   cli                                                    
                   xchg   eax,4*8[esi]     ; 4*8 est l'offset du handler
                   xchg   edx,4*8[edi]     ;  dtourner dans les tables  
                   sti                     ; d'interruptions              
                   mov    oldIRQ816,eax                                
                   mov    oldIRQ832,edx                                
                   ...                                                    
                   retn                                                   
      ...                                                                 
                                                                          
     ATTENTION:  d fait que l'interprtation des entres d'un IDT point
     par le registre IDTR  ne dpent que  du  mode en cours du processeur
     ( protg, rel, ou virtuel ) et  NON du type  de  code  par  dfaut
     ( 16-bit ou 32-bit ), la table d'interruption  du  mode rel, que le
     code s'excute en 16-bit ( par dfaut pour le DOS et le BIOS ) ou en
     32-bit, est identique : les entres de cette table occupent toujours
     4 octets; le  premier  mot dcrivant l'offset 16-bit, et le deuxime
     mot le segment 16-bit du vecteur d'interruption.                    
                                                                          
     CONSEQUENCE:  NE placez JAMAIS des routines d'interruption en dehors
     du premier 64 Ko d'un segment code.  D'une manire gnrale,  N'ex-
     cutez PAS du code 32-bit en-dehors de la limite de 64 Ko de segment,
     s'il fait appel aux interruptions internes  ou  si les interruptions
     externes ne sont pas dsactives!  
                                                                          
     Par ailleurs,  si vous comptez utiliser une pile 32-bit avec du code
     16-bit,  il vous faudra redfinir les  IRQ  sans quoi celles du BIOS
     ou d'autres programmes rsidents peuvent  planter  la machine.    
     En effet,  celles-ci  sont censes utiliser une pile 16-bit avec des
     rfrences externes. Il vous faudra donc rcrire les  IRQ  en sorte
     que ces dernires  appellent celles du BIOS aprs avoir commut dans
     une pile 16-bit. Vaste perspective...                               
                                                                          
   
   c) Les restrictions pour l'application iFM32:                           
                                                                            
      - Puisque qu'une application 32-bit  doit  pouvoir utiliser une pile
      32-bit, i.e, dont la taille excde 64 Ko, iFM32 se charge d'assurer
      la commutation d'un code 16/32-bit   un autre en mmorisant la pile
      de  l'ancien  code  et  en  restaurant  la  pile  du  nouveau  code;
      de ce fait,  le code 16-bit  est  assur de travailler avec une pile
      dont ESP n'excde pas 64 Ko, et le code 32-bit  avec  une vraie pile
      32-bit.  Notez toutefois que mme  sous un  code 16-bit, la pile est
      reconnue comme tant en 32-bit (ESP utilis et non SP, bit B = 1).  
      Par consquence,  il  faut  veiller  ne pas commuter d'un code  un
      autre  si  des  paramtres doivent tre passs dans la pile,  car le
      nouveau code  serait  incapable  d'y accder.  Une solution possible
      serait de commuter d'abord, puis d'empiler les paramtres,  et enfin
      d'appeler la routine en question. Une autre est de demander  passer
      d'une pile  une autre:                                             
                                                                          
      Exemple: L'accs  l'interruption " service16 " fonctionnant en code
      16-bit, exigeant trois paramtres passs dans la pile du code 16-bit
      est impossible  partir d'un code 32-bit  avec  sa  pile 32-bit.    
                                                                          
 	           .USE32                                                       
 	           ...                                                          
 	           push  paramater1                                             
 	           push  paramater2                                             
 	           push  paramater3                                             
 	           int   service16  < CRRAAAAASHH!!! (16-bit)                 
 	           ...                                                          
 	                                                                        
 	    En revanche, elle est possible pour un code 32-bit avec une pile 16-
 	    bit, comme c'est le cas ici:                                        
 	           ...                                                          
 	           int   0ACh        ; utilise la pile du code 16-bit           
 	           push  paramater1                                             
 	           push  paramater2                                             
 	           push  paramater3                                             
 	           int   service16  < OKKKK!!!                                
 	           int   0ADh        ; reprend la pile du code 32-bit           
 	           ...                                                          
 	                                                                        
 	    Fort heureusement, ces cas sont trs rares, car ni le DOS ni le BIOS
 	    ne font appel  la pile pour l'envoi des paramtres.            
 	                                                                        
 	                                                                        
 	    - Plusieurs segments  de  code  et  de  donnes peuvent cohabiter en
 	    16-bit ou en 32-bit. Il faudra juste veiller  excuter le  bon code
 	    avec le bon segment,  et    accder  aux bonnes donnes avec le bon
 	    adressage.                                                          
 	                                                                        
 	    - Le code doit imprativement se trouver dans les premiers 64 Ko des
 	    segments de code ( rien n'interdit d'en n'avoir plusieurs ).  Sinon,
 	    chaque  fois  que  EIP  excdera 65535, il faudra s'assurer qu'aucun
 	    IRQ, aucune interruption ou exception n'ait lieu; i.e, flag IF = 0. 
 	    Autrement, les segments de donnes peuvent excder les 64 Ko.       
 	                                                                        
 	    - Pour une raison bien dtermine, iFM32  ne supporte pas le mcha-
 	    nisme  de  la  pagination : le  mode rel  l'interdit  en  principe.
 	    Bien qu'il existerait une possibilit par le biais d'une instruction
 	    non documente " loadall ", elle est, d'une part, trs  coteuse  en
 	    cycles ( sans compter,  la ncessit de remettre  jour  beaucoup de
 	    registres, etc.), et,  d'autre  part, elle  n'est  plus  implmente
 	     partir des pentiums: l'astuce se rvlerait en faite infructueuse,
 	    puisqu'aprs tout, il s'agit de faire un DOS-extender 32-bit en mode
 	    rel qui soit justement plus  ais  d'utilisation que la plupart des
 	    DOS-extenders "traditionnels" (en mode virtuel)  et  plus  rapide si
 	    possible.                                                           
 	                                                                          

     

  Conclusion:
   

 Cette version d'iFM32 ne permet pas d'exploiter une pile 32-bit dans un
  code 16-bit sans quelques prcautions comme de dsactiver les IRQ  ou de
  les rcrire pour utiliser la pile 32-bit; cela permettrait aux program-
  meurs s'ils le dsirent,  d'crire des routines en code 16-bit qui pour-
  ront accder  la pile 32-bit du code 32-bit.  Bien entendu,  les inter-
  ruptions qui ne  seront  pas  du  cr  du programmeur, quant  eux,  de-
  vront tre " dtournes "  pour  assurer la transition d'une pile 32-bit
  vers la pile 16-bit pour leur bon fonctionnement et vice-versa pour leur
  retour  l'appelant. Pour cela, il vous faudra utiliser les trois tables
  d'interruption de iFM32 au lieu de deux par dfaut.                                                    
 Bien qu'en  principe  le  DOS  et  le  BIOS n'utilise gure la pile pour
  les passages des paramtres,  ils  existent  cependant un certain nombre
  de logiciels qui  utilisent  des  interruptions  ou  des "call far" avec
  passage des paramtres via la pile.  Une solution  ce genre de problme
  a t donn plus haut  mais  imposerait  au programmeur de constituer un
  ensemble de routines  qui aurait pour tche de grer ces particularits.                                                          

                           FIN DE FICHIER 

   
   
   
   
   
