home *** CD-ROM | disk | FTP | other *** search
/ DP Tool Club 24 / CD_ASCQ_24_0995.iso / dos / fr / hexutil / int_f.doc < prev   
Text File  |  1995-02-02  |  11KB  |  239 lines

  1.  
  2.  
  3.             Etude de l'évolution du pointeur de pile dans mes lanceurs
  4.         ----------------------------------------------------------
  5.  
  6.  
  7.     1) Fonctionnement d'une interruption:
  8.  
  9.  
  10.        Lors de l'appel d'une interruption on a dans l'ordre;
  11.  
  12.         a) Le registre des FLAGS est sauvé sur la pile.
  13.         b) Le registre IP est sauvé sur la pile.
  14.         c) Puis le registre CS est poussé sur la pile.
  15.             d) Le double mot sur lequel pointe l'INT représente la nouvelle
  16.            adresse CS:IP que l'on va charger. Et l'éxecution du
  17.            programme continu à cette adresse.
  18.  
  19.        Il faut noter que dans la table des INT qui va de 0000 à 03FF,
  20.        chaque vecteur d'INT occupe 2 mots ( un pour CS et l'autre pour IP )
  21.        soit 4 octets. Ce qui fait que lorsqu'on appelle par exemple l'INT
  22.        9 on ne va pas charger le mot à l'emplacement 9 dans IP et le
  23.        suivant dans CS. Il faut pour avoir l'adresse réelle ou se trouvent
  24.        les vecteurs CS et IP multiplier 9 * 4 ( puisque chaque INT prend
  25.        4 octets ) Et donc en 36 on trouve CS qui occupe l'octet 36 et 37
  26.        puis IP qui occupe les deux octets suivant soit 38 et 39. La
  27.        prochaine INT qui est la 10 commencera en 40. 
  28.         
  29.  
  30.     2) Pour simuler une INT on peut utiliser un CALLF et un PUSHF.
  31.  
  32.         a) Un PUSHF qui place le registre des FLAGS sur la pile.
  33.         b) Un CALLF lequel appelle la routine de l'INT considérée.
  34.  
  35.  
  36.     3) Cas de mes lanceurs:
  37.  
  38.  
  39.         a) L'INT 21 est détournée de son vecteur d'origine.
  40.         b) Le nouveau vecteur pointe sur une routine personnelle.
  41.         c) La fin de ma routine est un peu spéciale car soit on appelle
  42.            l'ancien vecteur de l'INT 21 par un CALL FAR et PUSHF, soit
  43.            on revient par un RETF corrigé.
  44.  
  45.  
  46.        Ci-dessous l'incrémentation/décrémentation du pointeur de pile lors
  47.        de l'appel de  l'INT 21 détournée;
  48.  
  49.                  .
  50.              .
  51.             │    .    │
  52.         │    .    │
  53.         │  Progr. │         L'INT 21 pousse ces
  54.         │principal│         3 REGS. sur la pile 
  55.         ├─────────┤         ┌──────────────┐
  56.             │ INT 21  │ ──────> │  PUSH Flags  │ SP-2
  57.  ────────── ├─────────┤         ├──────────────┤
  58.     SP=0    │  suite  │ <────┐  │ PUSH CS et IP│ SP-4      ┌────────────┐
  59.         │    .    │      │  └───────┬──────┘       │  Nouveau   │
  60.             │    .    │      │          │           │  vecteur   │
  61.                  .           │          └────────────────> ├────────────┤
  62.                  .         │                    8 Regs │  Push REGs │ SP-16
  63.                  │                   ├────────────┤
  64.                  │                   │ Traitement │
  65.                  │                   ├────────────┤
  66.                  │                8 Regs │  POP REGs    │ SP+16
  67.                  │                   ├────────────┤
  68.                              │                                    │
  69.                  │             Ici deux choix:      │                  
  70.                   │           ┌──────────────────────┤  Appel de
  71.                  │           │ Ou retour         │  l'ancien
  72.                              │             │ par RETF.            │  vecteur.
  73.                  │        ├────────────┤       ├────────────┤ 
  74.                  │        │  RETF + 2     │ SP+4+2  │ PUSH  Flags│ SP-2
  75.                  │      └──────┬─────┘         ├────────────┤
  76.                  │           │               │ CALL Far 21│ SP-4+6
  77.                  │             │               ├────────────┤
  78.                  │           │               │    IRET    │ SP+6
  79.                  │           │           └──────┬─────┘
  80.                  │           │                 │
  81.                  └─────────────┴──────────────────────┘        
  82.  
  83.                             Etat de la pile:
  84.  
  85.      Donc avant l'appel de l'INT:                SP=0
  86.  
  87.      Après l'appel de l'INT 21     :  SP-6         SP-6
  88.      Les PUSH de mon lanceur         :  SP-16               SP-22
  89.      Les POP de mon lanceur          :  SP+16               SP-6
  90.      1) Retour par RETF +2           :  SP+4+2=+6           SP=0       
  91.      2) Retour par CALLF+IRET        :  SP-2-4+6+6=+6       SP=0 
  92.  
  93.     Retour par RETF:
  94.     ----------------
  95.  
  96.       Le +2 qui suit le RETF dans le cas où l'on revient avec ce dernier
  97.       sert à aligner le pointeur de pile car le retour d'une INT se fait
  98.       par l'instruction IRET qui restaure IP ( +2 ), CS ( +2 ), puis le
  99.       registre des flags ( +2 ) ce qui fait +6. Alors que dans le cas
  100.       présent on revient avec un RETF qui lui ne restaure qu'IP et CS
  101.       ( +2 et +2 ) il manque donc les fameux +2 que l'on trouve dans
  102.       l'instruction RETF +2.
  103.  
  104.     Retour par CALLF et IRET:
  105.     -------------------------
  106.  
  107.       Certainement le plus compliqué à comprendre. Je pense que vous êtes
  108.       d'accord avec mes push/pop qui s'annullent avec -16 et +16. Ok, il
  109.       nous reste donc -6 dù au départ à l'appel de l'INT21. 
  110.       Alors voilà ce qui se passe maintenant: j'appelle l'INT 21 avec
  111.       un CALL Far donc -4 et un PUSHF donc -2.
  112.       (-4) + (-2) font -6 ( Vous m'arrêtez si vous avez des difficultés ).
  113.       On se retrouve maintenant dans l'INT 21 avec un SP à -12 (-6)+(-6).
  114.       On revient de l'INT 21 par un IRET dans mon lanceur ce qui fait 
  115.       -12+6=-6. Et de mon lanceur je refais un IRET pour le quitter
  116.       et revenir vers le programme appelant: donc encore une fois +6.
  117.       Et, comme vous l'aurez deviné: -6+6=0 !     
  118.    
  119.     Donc mon lanceur redonne bien correctement le control au programme
  120.         principal. Pourtant il y a une erreur d'écriture dans ce dernier qui
  121.     fait que certains de mes patchs ne fonctionnaient pas.
  122.     
  123.     Mon programme se plantait dans certain cas où l'un des flags était
  124.     testés lors du retour de l'appel de l'INT 21 pour la raison suivante:
  125.         Lors de l'appel de l'INT 21 le registre des flags est sauvé sur la
  126.     pile avant l'éxecution de ma routine. Puis ma routine est éxecutée
  127.     à son tour avant de simuler l'appel de l'INT 21 par un PUSH Flags
  128.     et un CALL far sur l'ancien vecteur de l'INT 21. Nous avons ici un
  129.     second PUSH flags qu'il est impossible d'éviter puisque toute inter-
  130.     ruption y est soumise en se terminant par un IRET qui restaure IP,
  131.     CS, et les flags. C'est donc le second PUSHF qui se retrouvait au
  132.     sommet de la pile lors du retour au programme principal et non plus
  133.     le premier qui avait été sauvé. Tant que mon traitement n'affectait
  134.     pas un des flags, le contenu du second PUSHF était égal au premier et
  135.     tout se passait sans problème. 
  136.     Dans le cas où mon traitement modifiait le contenu d'un des drapeaux
  137.     mais tant que celui-ci n'était pas testé au retour de ma routine
  138.     aucune interaction ne survenait. Mais il a suffit d'une fois dans le
  139.     programme XXXXXXXXXX pour me faire prendre conscience de ce bug !
  140.  
  141.     La solution consiste donc à faire un PUSH flags en même temps que mes
  142.     registres puis à les restaurer une fois le traitement terminé. 
  143.     Dans ce cas ma routine fonctionne correctement ( enfin ), et comme
  144.     l'on se trouve avec un POPF et un PUSHF avant l'appel de l'INT 21 par
  145.     le CALL far, celà permet de supprimer ces deux instructions. Un POP
  146.     et un PUSH s'annulent.
  147.     On obtient donc l'organigramme suivant:
  148.  
  149.                  .
  150.              .
  151.             │    .    │
  152.         │    .    │
  153.         │  Progr. │         L'INT 21 pousse ces
  154.         │principal│         3 REGS. sur la pile 
  155.         ├─────────┤         ┌──────────────┐
  156.             │ INT 21  │ ──────> │  PUSH Flags  │ SP-2
  157.  ────────── ├─────────┤         ├──────────────┤
  158.     SP=0    │  suite  │ <────┐  │ PUSH CS et IP│ SP-4      ┌────────────┐
  159.         │    .    │      │  └───────┬──────┘       │  Nouveau   │
  160.             │    .    │      │          │           │  vecteur   │
  161.                  .           │          └────────────────> ├────────────┤
  162.          .         │                   │ Push Flags │ SP-2
  163.          .         │                   ├────────────┤
  164.                  .         │                    8 Regs │  Push REGs │ SP-16
  165.                  │                   ├────────────┤
  166.                  │                   │ Traitement │
  167.                  │                   ├────────────┤
  168.                  │                8 Regs │  POP REGs    │ SP+16
  169.                  │                   ├────────────┤
  170.                              │                                    │
  171.                  │             Ici deux choix:      │                  
  172.                   │               ┌──────────────────────┤  Appel de
  173.                  │           │ Ou retour         │  l'ancien
  174.                              │             │ par RETF.            │  vecteur.
  175.                  │        ├────────────┤              │ 
  176.                  │        │   RETF+4      │ SP+4+4         │
  177.                  │      └──────┬─────┘         ├────────────┤
  178.                  │           │               │ CALL Far 21│ SP-4+6
  179.                  │             │               ├────────────┤
  180.                  │           │               │    IRET    │ SP+6
  181.                  │           │           └──────┬─────┘
  182.                  │           │                 │
  183.                  └─────────────┴──────────────────────┘        
  184.  
  185.  
  186.     Il existe aussi une autre solution qui est décrite ci-dessous en
  187.     utilisant uniquement un JMP FAR sur l'INT 21 ce qui évite de repasser
  188.     par mon lanceur au retour.
  189.  
  190.          .
  191.          .    
  192.         │    .    │
  193.         │  Progr. │
  194.         │principal│
  195.         ├─────────┤         ┌──────────────┐
  196.     SP=0    │ INT 21  │ ──────> │  PUSH Flags  │ SP-2
  197.  ────────── ├─────────┤         ├──────────────┤
  198.     SP=0    │  suite  │ <────┐  │ PUSH CS et IP│ SP-4      ┌────────────┐
  199.         │    .    │      │  └──────────────┘       │  Nouveau   │
  200.             │    .    │      │          │           │  vecteur   │
  201.                  .           │          └────────────────> ├────────────┤
  202.                  .         │                           │  Push REGs │ SP-X
  203.                  │                   │   + FLAGS  │
  204.                  │                   ├────────────┤
  205.                  │                   │ Traitement │
  206.                  │                   ├────────────┤
  207.                  │                   │  POP REGs    │ SP+X
  208.                  │                   │   + FLAGS  │
  209.                  │                   ├────────────┤
  210.                  │            Ancien Vecteur  ├─>│ JMPF INT 21│
  211.                  │                   └────────────┘
  212.                  └─────┤ Retour par une IRET de l'INT 21 ( SP+6 )
  213.  
  214.  
  215.     Le petit proggy AFF_INT.COM affiche de gauche à droite:
  216.  
  217.     - Le numéro de l'INT à partir de 00 jusqu'à FFh.
  218.     - La valeur du vecteur CS:IP sur lequel pointe l'INT considérée.
  219.     - La première instruction en HEXA allant être exécuté à l'emplacement
  220.       défini par ce vecteur.
  221.     - La traduction mnémonique en ASM permettant rapidemment de savoir
  222.       si l'INT en question est utilisée ou si elle retourne vers le
  223.       programme appellant avec une instruction IRET.
  224.     - Un commentaire.
  225.  
  226.     Nota: toutes les instructions ne sont pas décodées...
  227.  
  228.     Essai pratique:
  229.  
  230.     Lancer _DEBUG.COM en choississant l'observation octet mémoire ou IO.
  231.     Puis comme véhicule, utilisez une INT quelconque au choix, le
  232.     meilleur choix pourrait être dans la plage 78h à ECh - qui représentent
  233.     les INT non utilisées.
  234.     En lancant AFF_INT vous remarquerez que l'INT en question ne pointe
  235.     plus sur son vecteur d'origine et que sa première instruction est
  236.     un JMP ( première instruction de l'INT détournée de _DEBUG.COM ).
  237.  
  238.     FREDDY
  239.