Contacts

Introduction à la langue d'assembleur. Situations spéciales du mode V86

Les masmes d'assembleurs, TASM et WASM diffèrent les uns dans les autres. Cependant, la création de programmes simples pour eux n'a pratiquement pas de différences, à l'exception de l'assemblage et de la mise en page elle-même.

Donc, notre premier programme pour MASM, TASM et WASM, qui affiche la lettre anglaise "A" dans la position du curseur actuel, c'est-à-dire à gauche coin supérieur Écran:

Modèle minuscule .Code Org 100h Démarrage: MOV AH, 2 MOV DL, 41H INT 21H INT 20H End Start Ce texte peut être saisi dans n'importe quel simple. éditeur de texte - Par exemple, dans le bloc-notes de Windows (mais pas en mot et non dans un autre "délicat"). Cependant, je recommande l'éditeur de texte "avancé" avec une illumination de syntaxe, par exemple PSPAD (voir la section). Ensuite, enregistrez ce fichier avec extension.asm, par exemple dans le dossier MyProg. Appelons le fichier ATEST. Donc, nous avons eu: c: \\ myProg \\ atestest.asm.

REMARQUE
Veuillez noter que dans la première équipe, nous avons enregistré 2 au lieu de 02h. Masmes, Tasmes et Wasm, comme EMU8086, admettent une telle "liberté". Bien que vous puissiez écrire 02h - il n'y aura pas d'erreurs.

Explication du programme:

.Model minuscule - 1ère ligne. Dirive.Model Définit un modèle de mémoire pour un type de fichier spécifique. Dans notre cas, il s'agit d'un fichier avec COM Extension, nous sélectionnons donc le modèle minuscule, dans lequel les segments du code, des données et de la pile sont combinés. Le minuscule modèle est conçu pour créer des fichiers de type SOM.

.code. - 2ème ligne. Cette directive commence le segment de code.

Org 100h. - 3ème chaîne. Cette commande définit la valeur du compteur de logiciel en 100h, car lors du chargement du fichier SOM en mémoire, DOS sélectionne les 256 premiers octets sur le bloc de données PSP pour les 256 premiers octets (nombre décimal 256 égal à Hexadecimal 100h). Le code de programme est situé uniquement après ce bloc. Tous les programmes compilés dans les fichiers COM doivent commencer par cette directive.

commencez: MOV AH, 02H - 4ème ligne. Start Label est situé en face de la première commande du programme et sera utilisé dans la directive finale pour spécifier quelle commande commence le programme. L'instruction MOV place la valeur du deuxième opérande au premier opérande. C'est-à-dire que la valeur de 02H est placée dans le registre EN. De quoi est-ce fait? 02h est une fonction DOSOVA qui affiche un symbole à l'écran. Nous écrivons un programme pour DOS, nous utilisons donc les commandes de cette système opérateur (OS). Et nous écrivons cette fonctionnalité (ou plutôt son nombre) dans le registre FR, car l'interruption 21H utilise ce registre particulier.

MOV DL, 41H - 5ème ligne. Le code de symbole "A" est entré dans le registre DL. Le code "A" en fonction de la norme ASCII est le numéro 41H.

Int 21h. - 6ème ligne. Il s'agit de la plus grande interruption de 21H - une commande qui provoque la fonction système DOS spécifiée dans le registre FR (dans notre exemple est une fonction de 02h). La commande INT 21H est le principal moyen d'interaction des programmes du système d'exploitation.

Int 20h. - 7ème ligne. Cette interruption qui rapporte le système d'exploitation sur la production du programme et le transfert de gestion application de la console. Dans le cas où le programme est déjà compilé et exécuté à partir du système d'exploitation, la commande INT 20H nous renvoie à OS (par exemple, dans DOS).

Fin début. - 8ème ligne. La directive finale complète le programme en même temps indiquant quelle étiquette doit être exécutée.

Int 3.

Appelez l'interruption 3 (#bp, point d'arrêt)

8086

int 3.

CD ib.

Int. iMM8.

Interruption du défi iMM8.

8086

int 13.

Dans

Appel d'interruption 4 (#of, débordement) si eflags.of \u003d 1

8086

dans

La description:

Équipe Int 3. Il est destiné à générer une interruption 3 et à décrire l'opération identique à la commande INT N, sauf que le numéro d'interruption n'est pas présent directement dans le code de fonctionnement, mais définit implicitement égal à 3.

Cette interruption est destinée à être utilisée par le débogueur, qui place une commande à une seule tonalité spéciale. Int 3. (Code CCCH) au lieu du premier octet de commande ou au lieu de commandes à sens unique.

Il existe une seconde façon d'appeler pour cette interruption à l'aide d'un code de deux octets INT 3 (code CD03H). mais cette méthode En pratique, il ne s'applique pas, tous les assembleurs X86 sont par défaut par défaut Mnemonics Int 3. En tant que commande simple ton avec code CCH (mais cela n'exclut pas la possibilité d'une programmation manuelle de deux octets). En plus de la taille du code, le processus de traitement des commandes unique et à deux octets est différent. Int 3.. L'interruption générée par une commande monocommande en mode EV86 (CR4.VME \u003d 1) n'est pas exposée à la redirection de la carte de redirection d'interruption (comme décrit pour le mode 2, le mode 3, le mode 5) et est toujours traitée par le gestionnaire de mode protégé à travers le descripteur dans la table IDT. De plus, en mode V86, les vérifications de champ IOPL ne sont pas cochées pour cette interruption et, en conséquence, l'erreur ne peut pas être générée #gp error quand eflagS.IOPL< 3, то есть однобайтная команда не является IOPL-чувствительной .

Opération:

L'algorithme présenté ici décrit non seulement le comportement du processeur lors de l'exécution de la commande. Int 3. Interruption externe ou génération d'une situation particulière.

Ensuite aller à. Mode d'adresse réelle;

If (eflags.vm \u003d 1 et eflags.IOPLL< 3 AND

(Cr4.vme \u003d 0 ou cr4.vme \u003d 1 et irb [n] \u003d 1)

) (* IRB [N] - BIT, correspondant à l'interruption de N dans la carte de la redirection des interruptions *)

#Gp (0); (Software interrompt INT N en mode: (1) V86 à EFLAGS.IOPL< 3, (2) EV86 Режим 2 *)

AUTRE. (* Mode protégé ou mode V86 / EV86 *)

Si (eflags.vm \u003d 1 et cr4.vme \u003d 1 et

(Int n) et irb [n] \u003d 0)

Sinon goto. Mode protégé.; (* Interruptions matérielles, situations spéciales; Interruptions logicielles INT N: (1) Mode protégé, (2) V86 avec EFLAGS.IOPL \u003d 3, (3) Mode EV86 1 ou 4 *)

Mode réel-addres:

Si ((numéro d'interruption * 4) + 3 va au-delà du segment lors de l'accès à la table des vecteurs d'interruption IVT), alors #gp; Fi;

Si (il n'y a pas de place pour 6 octets dans la pile), alors #ss; Fi;

Eflags.if \u003d 0; (* Réinitialiser le drapeau des interruptions *)

Eflags.tf \u003d 0; (* Réinitialiser les pièges de drapeau *)

Eflags.ac \u003d 0; (* Réinitialiser le drapeau du mode de contrôle d'alignement *)

Cs \u003d ivt [numéro d'interruption * 4] .selector;

EIP \u003d IVT [Numéro d'interruption * 4]. Fffset et 0x0000FFFFFH;

(* Continuation du travail en adressage réel ... *)

EV86-MODE: (* Cr0.pe \u003d 1, eflags.vm \u003d 1, cr4.vme \u003d 1, mode EV86 est une interruption du programme INT N, avec irb [N] \u003d 0 - mode 3 ou mode 5 *)

Si (dans la pile de tâches V86, il n'y a pas d'espace pour 6 octets), alors #ss (0); Fi;

tempFlags \u003d drapeaux;

tempflags.nt \u003d 0;

Puis eflags.if \u003d 0; (* Réinitialiser le drapeau de la permission d'interruptions *)

tempflags.if \u003d eflags.vif;

Eflags.vif \u003d 0; (* Réinitialisation du drapeau virtuel des interruptions *)

Eflags.tf \u003d 0; (* Réinitialiser les pièges de drapeau *)

Pousser (TempFlags);

(* Les codes d'erreur ne sont pas entrés sur la pile *)

Cs \u003d ivt_v86 [Numéro d'interruption * 4] .Selector; (* Tableau des vecteurs d'interruption IVT_V86 est situé au début de l'espace d'adressage de la tâche V86 *)

EIP \u003d ivt_v86 [Numéro d'interruption * 4] .Offset et 0x0000FFFFFH; (* L'ancien registre EIP 16 bits est réinitialisé *)

(* Travail continu dans EV86 ... *)

MODE PROTÉGÉ: (* Cr0.pe \u003d 1, interruptions matérielles, situations spéciales; Interruptions logicielles INT N en mode: (1) Mode protégé, (2) V86 avec EFLAGS.IOPL \u003d 3, (3) MODE EV86 1 ou MODE 4 *)

Si ((numéro d'interruption * 8) + 7 ne tombe pas dans l'IDT) TAN #GP (numéro d'interruption * 8 + 2 + EXT); Fi;

(* Ci-après, dans les paramètres de code d'erreur, le terme +2 signifie définir le code d'erreur du code d'erreur et les termes + ext-moyen de définir le code d'erreur ext conformément à la question de savoir si l'erreur a provoqué le programme d'interruption EXTER \u003d 0 ou externe ext \u003d 1 *)

AR Descripteur octet doit définir la passerelle d'interruption, une passerelle d'interruption ou une passerelle de tâche, sinon #gp (numéro d'interruption * 8 + 2 + ext);

Si (interruption logicielle ou situation spéciale) (* Ceux. Un des cas INT N, INT 3, INT01, lié ou en *)

Si (Cpl\u003e passerelle DPL)

#Gp (numéro d'interruption * 8 + 2); (* Cr0.pe \u003d 1, passerelle DPL< CPL, программное прерывание *)

La passerelle doit être présente, sinon #np (numéro d'interruption * 8 + 2 + EXT);

Si (tâches de passerelle)

Ensuite aller à. Task-Gate.;

Aller à. Piège-or-int-gate; (* Cr0.pe \u003d 1, interruption ou passerelle de piège *)

Piège ou-int-gate: (* Mode protégé ou mode V86 / EV86, passerelle ou passerelle d'interruption *)

Vérification du nouveau sélecteur CS spécifié dans le descripteur de passerelle et le descripteur approprié de LDT ou GDT:

Le sélecteur ne doit pas être nul, sinon, #gp (ext);

L'indice sélecteur doit tomber dans la table descripteurs, sinon #gp (sélecteur + ext);

La poignée sélectionnée doit être un code de descripteur de segment, sinon #gp (sélecteur + ext);

Le segment doit être présent (p \u003d 1), sinon #np (sélecteur + poste);

Si (segment de code non coordonné) et (Code segment DPL< CPL)

Si eflags.vm \u003d 0

Ensuite aller à. Int-inter-privilégié; (* Cr0.pe \u003d 1, eflags.vm \u003d 0, interruption ou passerelle piège, segment de code incohérent, segment de code DPL< CPL *)

Sinon (* eflags.vm \u003d 1 *)

Si (DPL du nouveau segment de code ≠ 0), alors #gp (SELector Code Segment + EXT); Fi;

Aller à. Int-from-v86-mode;(* Cr0.pe \u003d 1, eflags.vm \u003d 1, interruption ou passerelle piège, segment de code DPL \u003d 0, cpl \u003d 3 *)

AUTRE. (* CR0.PE \u003d 1, interruption ou passerelle piège, segment de code cohérent ou segment de code incohérent avec Dpl \u003d CPL *)

Si eflags.vm \u003d 1 alors #gp (sélecteur de segment de code + ext); Fi;

Si ((correspondant correspondant) ou (Code Segment Dpl \u003d CPL))

Ensuite aller à. Int-to-in-intra-priva; (* Cr0.pe \u003d 1, passerelle d'interruption ou piège, segment de code DPL ≤ CPL pour un segment cohérent, le segment de code Dpl \u003d CPL pour segment incohérent *)

Sinon #gp (sélecteur de segment de code + ext); (* DPL\u003e CPL pour un segment cohérent ou DPL ≠ CPL pour un segment incohérent *)

Int-to-Inter-Priv: (* Mode protégé, interruption ou passerelle piège, segment de code incohérent, segment de code DPL< CPL *)

Si (actuel TSS 32 bits)

Tssstackaddress \u003d (nouveau segment de code DPL * 8) + 4

Si ((Tssstackaddress + 5)\u003e Limite TSS) (* (Tssstackaddress + 7)\u003e

News \u003d [TSS + tssstackaddress + 4] Base; (* 2 octets chargés *)

(* 4 octets chargés *)

AUTRE. (* TSS actuel 16 bits *)

Tssstackaddress \u003d (nouveau segment de code DPL * 4) + 2

Si ((Tssstackaddress + 3)\u003e Limite TSS) (* (Tssstackaddress + 4)\u003e Limite TSS - pour certains modèles de processeur *)

Alors #ts (sélecteur de TSS + ext actuel);

Newesp \u003d [TSS + tssstackaddress Base]; (* 2 octets chargés *)

Nouvelles \u003d [TSS + tssstackaddress + 2 base]; (* 2 octets chargés *)

Le sélecteur RPL doit être égal à la DLL du nouveau segment de code, sinon #TS (sélecteur SS + ext);

Le DPL du segment de pile doit être égal à la DLL du nouveau segment de code, sinon #TS (sélecteur SS + EXT);

Si (passerelle 32 bits)

Ensuite, une nouvelle pile devrait avoir lieu pendant 20 octets (24 octets, s'il existe un code d'erreur), sinon #ss (ext)

Sinon, la nouvelle pile doit avoir lieu pendant 10 octets (12 octets, s'il ya un code d'erreur), sinon #ss (ext)

SS: ESP \u003d TSS (News: NewSesp); (* Téléchargez les nouvelles valeurs SS et ESP à partir de TSS *)

Si (passerelle 32 bits)

Puis.

Autre CS: IP \u003d porte (sélecteur: offset);

Télécharger SS Descripteur dans la partie cachée du registre SS;

Si (passerelle 32 bits)

Pousser (pointeur long sur l'ancienne pile - SS: ESP);

Pousser (pointeur long sur point de retour - CS: EIP); (* 3 mots sont complétés à 4 *)

Pousser (code d'erreur);

Pousser (pointeur long sur l'ancienne pile - SS: SP); (* 2 mots *)

Pousser (pointeur long sur point de retour - CS: IP); (* 2 mots *)

Pousser (code d'erreur);

CPL \u003d DPL du nouveau segment de code;

Si (interrompre la passerelle) alors eflags.if \u003d 0 fi; (* Réinitialiser le drapeau d'interruption *)

Eflags.rf \u003d 0;

(* Continuation du travail en mode protégé à un niveau avec de grands privilèges ... *)

Int-from-v86-mode: (* Mode V86 / EV86, interruption ou passerelle piège, dpl \u003d 0, cpl \u003d 3 *)

(* TSS actuel est toujours 32 bits en mode V86 *)

Si (TSS limite< 9) (* Limite TSS< 11 - для некоторых моделей процессоров *)

Alors #ts (sélecteur de TSS + ext actuel);

Newss \u003d [Base TSS + 8]; (* 2 octets chargés *)

Newesp \u003d [base TSS + 4]; (* 4 octets chargés *)

Vérifiez le sélecteur du nouveau segment de pile des nouvelles et du descripteur approprié de LDT ou GDT:

Le sélecteur ne doit pas être zéro, sinon #ts (ext);

L'indice sélecteur doit tomber dans la table descripteur, sinon les #ts (ss sélecteur + ext);

Le sélecteur RPL devrait être zéro, sinon #ts (ss sélecteur + ext);

Le DLL du segment de pile doit être zéro, sinon les #ts (sys sélecteur + ext);

Le descripteur doit avoir un format de descripteur de descripteur de données autorisé pour l'enregistrement (W \u003d 1), sinon #ts (sélecteur SS + poste);

Le segment doit être présent (p \u003d 1), sinon #ss (sys sélecteur + ext);

Si (passerelle 32 bits)

La nouvelle pile devrait avoir lieu pendant 36 octets (40 octets, s'il existe un code d'erreur), sinon #ss (ext)

Le nouvel indicateur de l'instruction devrait tomber dans le nouveau segment de code, sinon #gp (ext); (* Le pointeur d'instructions est déterminé par la valeur de champ offset du descripteur de passerelle *)

Tempeflags \u003d EFLAGS;

Eflags.vm \u003d 0; (* Le processeur sort du mode V86 pour traiter l'interruption en mode protégé *)

Si (interrompre la passerelle)

Puis eflags.if \u003d 0;

Cpl \u003d 0; (* Passez au niveau de privilège zéro *)

SS: ESP \u003d TSS (News: NewSesp); (* Téléchargez les valeurs SS0 et ESP0 de TSS *)

Pousser (GS);

Pousser (fs); (* Se développe à deux mots *)

Pousser (DS); (* Se développe à deux mots *)

Pousser (es); (* Se développe à deux mots *)

Gs \u003d 0; (* Les registres segments sont réinitialisés. Il est inacceptable d'une utilisation ultérieure de sélecteurs zéro en mode sécurisé *)

Pousser (Temps); (* Se développe à deux mots *)

Pousser (Tempeflags);

Pousser (CS); (* Se développe à deux mots *)

Pousser (code d'erreur); (* Si présent, 4 octets *)

CS: EIP \u003d porte (sélecteur: offset); (* Sélecteur de téléchargement: Décalage du descripteur de passerelle 32 bits *)

Sinon (une passerelle * 16 bits *)

La nouvelle pile doit avoir lieu pendant 18 octets (20 octets, s'il ya un code d'erreur), sinon #ss (ext)

(* L'épargne dans une pile de registres de 16 bits survient de la même manière à une passerelle 32 bits *)

(* Retour de l'interruption avec la commande IREET Retour au mode V86 à partir du segment de 16 bits ne sera pas possible, car le drapeau VM ne sera pas enregistré dans la pile et ne sera pas récupéré à partir de l'image de EFLAGS lors de son retour * )

(* Continuation du travail en mode protégé au niveau zéro des privilèges ... *)

Int-to-intra-priva: (* Cr0.pe \u003d 1, dpl \u003d cpl ou segment cohérent avec DPL ≤ CPL *)

Si (passerelle 32 bits)

Ensuite, une nouvelle pile devrait avoir lieu pendant 12 octets (16 octets, s'il existe un code d'erreur), sinon #ss (ext)

Sinon la nouvelle pile devrait avoir lieu pendant 6 octets (8 octets, s'il existe un code d'erreur), sinon #ss (ext)

Le nouvel indicateur de l'instruction devrait tomber dans le nouveau segment de code, sinon #gp (ext);

Si (passerelle 32 bits)

Pousser (pointeur long au point de retour); (* 3 mots sont complétés à 4 *)

CS: EIP \u003d porte (sélecteur: offset); (* Sélecteur de téléchargement: Décalage du descripteur de passerelle 32 bits *)

Pousser (code d'erreur); (* Si présent, 4 octets *)

Pousser (pointeur long au point de retour); (* 2 mots *)

CS: IP \u003d porte (sélecteur: offset); (* Sélecteur de téléchargement: Décalage du descripteur de passerelle 16 bits *)

Pousser (code d'erreur); (* Si présent, 2 octets *)

Téléchargez CS Descripteur dans la partie cachée du registre CS;

If (interrompt la passerelle) alors eflags.if \u003d 0; Fi;

(* Continuation du travail en mode protégé sans changer le niveau de privilège ... *)

Task-Gate: (* Cr0.pe \u003d 1, passerelle de tâches *)

Vérifiez le sélecteur TSS de la passerelle de tâches Description:

Le sélecteur doit définir GDT (bit ti \u003d 0), sinon #gp (sélecteur TSS + EXT);

L'indice sélecteur doit tomber dans la table GDT, sinon #GP (sélecteur TSS + EXT);

Vérification du descripteur TSS correspondant correspondant au sélecteur sélectionné:

Le descripteur TSS doit avoir un type de TSS libre (type.b \u003d 0), sinon #gp (sélecteur TSS + ext);

TSS doit être présent (p \u003d 1), sinon #np (sélecteur TSS + EXT);

Tâches de commutation (avec pièce jointe) dans TSS; (* Ici "avec l'attachement" désigne le fait que lors de l'initialisation du contexte d'une nouvelle tâche sera défini par le drapeau EFLAGS.NT \u003d 1, et la tâche sélecteur TSS (ancienne) sera copiée dans le segment TSS (ancien). Segment - Voir Adresse et multitâche: signifie support multisascia *)

Si (interruption est une situation particulière avec le code d'erreur)

La pile doit être un lieu pour le code d'erreur, sinon #ss (ext);

Pousser (code d'erreur);

Le pointeur d'instruction EIP doit tomber dans le segment CS, sinon #gp (ext);

(* Chargement du contexte d'une nouvelle tâche est accompagné de vérifications supplémentaires telles que décrites dans la section Adressage et multitâche: moyen de support multi-altitude *)

(* Continuation du travail dans le contexte d'une nouvelle tâche ... *)

Situations spéciales de régime protégé:

Int 3.Mais aussi à la réception de toute interruption externe ou génération d'une situation particulière. Bit Ext. Dans le code d'erreur de l'interruption externe).

  • descripteur vecteur (index) d'interruptions ne se trouve pas dans le tableau des descripteurs d'interruption (IDT);
  • descripteur vecteur (index) de l'interruption, n'est pas un descripteur de passerelle piège, une passerelle d'interruption ou une passerelle de tâches;
  • il existe une interruption logicielle ou une situation spéciale logicielle (c'est-à-dire l'un des cas: INT N, INT 3, INT01, lié ou dans) et en même temps niveau de privilège actuel (CPL) tâches plus niveaux de privilège(DPL) descripteur de passerelle De la table IDT -
  • sélecteur de segment dans le traitement approprié vecteur (Index) d'interrompre le descripteur de passerelle d'interruption, la passerelle d'interruption ou la passerelle de tâches est un sélecteur zéro;
  • la sélection du segment segment de la passerelle piège ou du descripteur d'interruption ne tombe pas dans la table correspondante des descripteurs;
  • l'indice sélecteur TSS de l'interruption correspondante du descripteur de passerelle de tâche ne tombe pas dans table de descripteur globale (GDT);
  • descripteur Le nouveau segment de code n'est pas un descripteur de secteurs de code;
  • (DPL) Nouveau segment de code coordonné privilège de niveau actuel Tâches (CPL) -
  • descripteur de niveau de privilèges (DPL) du nouveau segment de code incohérent n'est pas égal niveau de privilège actuel Tâches (CPL) -
  • sélecteur TSS de l'interruption correspondante du descripteur de passerelle de tâche indique descripteurs de table locaux (LDT);
  • le descripteur TSS de la nouvelle tâche est noté comme occupé- Type.b ≠ 1.
  • l'adresse sur laquelle la nouvelle valeur doit être lue pour pointeur de pile (SS: ESP), va au-delà du segment TSS;
  • la sélection du nouveau segment de pile est un sélecteur zéro;
  • l'indice sélecteur du nouveau segment de pile ne relève pas de la table correspondante des descripteurs;
  • le niveau demandé des privilèges (RPL) La sélection du nouveau segment de pile n'est pas égale (DPL) New Code Segment -
  • descripteur de niveau de privilèges (DPL) du nouveau segment de pile n'est pas égal descripteur de niveau de privilèges (DPL) New Code Segment -
  • le nouveau segment de pile n'est pas un segment de données disponible pour l'enregistrement -
  • l'interruption correspondante du descripteur de passerelle piège, la passerelle d'interruption, la passerelle de tâche ou le descripteur TSS est marqué comme non accompagné (Bit P Descripteur est réinitialisé);
  • le nouveau segment de code n'est pas présent (bit P. Le descripteur de segment est réinitialisé).
  • lorsque vous écrivez sur la pile (y compris dans une nouvelle pile, si les valeurs de commutation de pile) adresses de retour, pointeur de pile, drapeaux ou code d'erreur convient au bord de la bordure admissible du segment de pile;
  • le nouveau segment de pile n'est pas présent (le descripteur de bits P segment est réinitialisé).

Situations particulières de régime d'adressage réel:

La liste des situations spéciales présentées ici caractérise le comportement du processeur non seulement lors de l'exécution de la commande. Int 3.Mais aussi à la réception de toute interruption externe ou génération d'une situation particulière.

Situations spéciales du mode V86:

La liste des situations spéciales présentées ici caractérise le comportement du processeur non seulement lors de l'exécution de la commande. Int 3.Mais aussi à la réception de toute interruption externe ou génération d'une situation particulière. Bit Ext. Dans le code d'erreur, il est utilisé pour indiquer externe par rapport au programme d'événements interrompu (

Toutes les fonctions DOS sont appelées en interrompant 21h (en notation décimale 33). La première version de DOS contenait 42 fonctions. Dans la seconde, 33 autres fonctions sont ajoutées à elles, qui sont stockées dans toutes les versions ultérieures. Le choix d'une fonction spécifique est effectué en enregistrant le numéro correspondant au registre AH.

Fonction 02: Sortie Symbole Simple à l'écran

Pour produire un caractère sur l'écran PC utilisé

fonction d'interruption 21H 02:

mOV DL,<код выводимого символа>

Le symbole de sortie est mis en surbrillance dans la position du curseur (tout ce qu'il est enregistré), après quoi le curseur se déplace vers une position à droite. Si le curseur était à la fin de la chaîne d'écran, il se déplace au début de la ligne suivante et si le curseur était à la fin de la dernière ligne de l'écran, le contenu de l'écran déplace une ligne vers le haut et le vide La chaîne apparaît en bas et le curseur est installé.

Les symboles avec des codes 7, 8, 9, 10 (0AH) et 13 (0HDH) sont effectués de manière particulière. Symbole avec code 7 (cloche, appel) à l'écran n'est pas souligné (et le curseur ne se déplace pas) et provoque des causes signal sonore. Symbole avec code 8 (backspase, pas en arrière) renvoie le curseur à une position à gauche, sauf si elle était dans la ligne gauche de la chaîne. Le symbole avec code 9 (onglet, onglet) déplace le curseur à droite à la position la plus proche, multiple 8. Le symbole avec code 10 (flux de ligne, ligne traduire) déplace le curseur sur la chaîne de ligne suivante, en laissant le même colonne. Symbole avec code 13 (Carrige Retour, le retour du chariot) Définit le curseur au début de la ligne actuelle; Conclusion dans une rangée de caractères avec des codes 13 et 10 signifie traduire un curseur au début de la ligne suivante.

Fonction 9: Afficher une chaîne sur l'écran d'affichage

Pour afficher la chaîne (séquences de symboles), vous pouvez, bien sûr, utiliser la fonction 02, mais elle peut être effectuée en une seule réception à l'aide d'une fonction d'interruption de 21h 09:

DX: DX: \u003d Démarrer l'adresse de la ligne

Avant de faire référence à cette fonction, le numéro du segment de mémoire doit être placé dans le registre DS, dans lequel la ligne de sortie est située et dans le registre DX - le décalage de la ligne à l'intérieur de ce segment. Dans le même temps, à la fin de la ligne, il devrait y avoir un symbole $ (code 24h), qui sert de signe de la fin de la ligne et n'est pas affiché.

Bien que cette fonctionnalité puisse être beaucoup plus pratique pour les fonctions Sortie pointilleuse à l'écran (fonction 2 et 6), elle présente l'inconvénient qu'un symbole entièrement ordinaire $ est utilisé comme limiteur de chaîne. Ceci est une autre compatibilité des produits latéraux avec CP / M.

Système d'exploitation avancé DOS fonctionne comme un limiteur de chaîne Utilisation de CRR $ (0). Cela est conforme aux accords adoptés dans le système d'exploitation UNIX et au langage de programmation SI.

Il n'y a pas de telle chose chez les fonctions DOS qui affiche des chiffres. Une telle opération, si nécessaire, doit être mise en œuvre sur la base des fonctions considérées.

Fonction 4CH: Achèvement du programme

Après avoir terminé toutes ses actions, le programme est obligé de renvoyer la gestion du système d'exploitation afin que l'utilisateur puisse continuer à fonctionner sur le PC. Un tel remboursement est mis en œuvre par la fonction d'interruption de 21h, qui est placée à la fin du programme:

mOV al,<код завершения>

Chaque programme, d'une manière générale, est obligé de faire rapport, avec succès ou non ses travaux. Le fait est que tout programme s'appelle d'un autre programme (par exemple, du système d'exploitation), et parfois appelé le programme pour continuer à fonctionner correctement, vous devez savoir si le programme appelé est rempli, ou il a fonctionné avec un Erreur. Ces informations sont transmises comme code de remplir le programme (certains entier), qui devraient être nulles si le programme a fonctionné correctement et non nul (spécifiquement stipulé dans chaque cas) sinon. (Vous pouvez apprendre le code d'achèvement du programme appelé à l'aide de la fonction d'interruption de 4DH 21H.) Ce code sera requis ou non, le programme doit toujours le donner.

Qu'est-ce que l'assembleur

L'assembleur est un langage de programmation de bas niveau. Pour chaque processeur, il y a un assembleur. Programmation sur l'assembleur Vous travaillez directement avec l'instrument informatique. Le texte source de la langue d'assembleur est constitué de commandes (mnémoniques), qui, après compilation, sont converties en codes de commande processeur.

Le développement de programmes sur l'assembleur est une chose très difficile. Au lieu du temps passé du temps, vous recevez un programme efficace. Les programmes d'assembleurs sont rédigés lorsque chaque cycle de processeur est important. À l'assembleur, vous donnez des commandes spécifiques au processeur et aux ordures supplémentaires. Ceci est réalisé par une grande vitesse de votre programme.

Pour utiliser avec compétence l'assembleur, vous devez connaître le modèle logiciel de microprocesseur. Du point de vue du programmeur, le système de microprocesseur consiste en:

  1. Microprocesseur
  2. Mémoire
  3. Périphériques d'E / S.

Le modèle logiciel est bien décrit dans la littérature.

Syntaxe d'assembleur

Format général de la chaîne de programme sur assembleur

<Метка>: <Оператор> <Операнды> ; <Комментарий>

Mots clés. L'étiquette peut être constituée de caractères et de signes d'adhésion. Les balises sont utilisées dans des opérations de transition conditionnelles et inconditionnelles.

Champ d'opérateur. Ce champ contient une équipe mnémonique. Par exemple, mnemonica mOV.

Terrain d'opérande. Les opérandes ne peuvent être présents que si l'opérateur est présent (champ opérateur). Les opérandes peuvent ne pas être, et peut-être plusieurs. Les opérandes peuvent être des données que vous devez effectuer certaines actions (avant, pli, etc.).

Champ de commentaire. Le commentaire est nécessaire pour le soutien verbal du programme. Tout ce qui est derrière le symbole ; Il est considéré comme un commentaire.

Le premier programme dans la langue des assembleurs

Cet article utilisera un assembleur pour le processeur I80X86 et le logiciel suivant est utilisé:

  • Tasmes - Assembleur de Turbo Borland - Compilateur
  • TLINK - Borland Turbo Linker - Éditeur de communications (Linker)

Être concret, TASM 2.0.

Par tradition, notre premier programme retirera la chaîne "Hello World!" sur l'écran.

File Sample.asm.

Modèle petit; Memory Model.Stack 100h; Définir la pile taille.data; Le début du segment de données du programme Hellomsg DB "Hello World!", 13.10, "$" .code; Le début du segment de code MOP AX, @ données; Nous envoyons l'adresse du segment de données au registre AX MOV DS, AX; Installation du registre DS sur le segment de données MOV AH; Fonction de sortie de ligne DOS sur l'écran MOV DX, décalée Hellomsg; Nous spécifions le décalage au début de la ligne INT 21H; Nous affichons la chaîne de Mov AX, 4C00H; Fonction DOS sortie du programme INT 21H; Sortir de fin

Comme vous remarquerez peut-être que le programme est divisé en segments: segment de données, segment de code et il y a un autre segment de pile.

Considérez tout dans l'ordre.

Directive.Model Small Spécifie le modèle de mémoire. Petit modèle est 1 segment pour code, 1 segment pour les données et la pile IE Les données et la pile sont dans le même segment. Il existe d'autres modèles de mémoire, par exemple: minuscule, moyen, compact. Selon le modèle de mémoire que vous avez choisi, vos segments de programme peuvent se chevaucher ou avoir des segments distincts en mémoire.

Directive.Stack 100h définit la taille de la pile. La pile est nécessaire pour enregistrer certaines informations avec sa récupération ultérieure. En particulier, la pile est utilisée lors d'interruptions. Dans ce cas, le contenu du registre des drapeaux Flags Drapeaux, CS Register et IP sont empilés. Ensuite, il y a un programme d'interruption, puis il est restauré par les valeurs de ces registres.

  • Les drapeaux Flags Inscrivez-vous contiennent des signes formés après avoir exécuté la commande au processeur.
  • CS Register (segment de code) contient l'adresse du segment de code.
  • Le registre IP (pointeur d'instructions) est un pointeur de commande. Il contient l'adresse de la commande qui doit être remplie ensuite (adresse relative au segment de code CS).

Suite description détaillée Entrer dans le cadre d'un article simple.

Directive.Data détermine le début du segment de données de votre programme. Le segment de données définit les "variables", c'est-à-dire. Il y a une redondance de la mémoire dans les données requises. Après.Data va chaîne
Hellomsg db "bonjour monde!", 13.10, "$"

Ici Hellomsg est un nom symbolique qui correspond au début de la ligne "Hello World!" (sans citations). C'est-à-dire que c'est l'adresse du premier symbole de notre chaîne par rapport au segment de données. La directive DB (Définir l'octet) définit la zone de mémoire disponible en contournement. 13.10 - Codes symboliques Nouvelle ligne Et le retour du chariot et le symbole $ est requis pour le bon fonctionnement de la fonction DOS 09h. Donc, notre chaîne occupera une mémoire de 15 octets.

Directive. Code détermine le début du segment de code (segment CS - Code) du programme. Ensuite, les rangées du programme contenant les mnémoniques des équipes.

Je vais vous parler de l'équipe MOV.

mOV.<приёмник>, <источник>

Commande MOV - Envoyer la commande. Elle transmet le contenu de la source dans le récepteur. Le transfert peut être un registre de registre, enregistrer, registre de mémoire, mais il n'y a pas de mémoire de mémoire de transfert. Tout passe dans les registres du processeur.

Pour travailler avec les données, vous devez configurer le registre du segment de données. Le réglage est que nous enregistrons l'adresse de segment de données @Data dans le registre DS (segment de données). Enregistrez directement l'adresse dans ce registre n'est pas possible - c'est l'architecture, nous utilisons donc le registre AX. À la hache, nous écrivons une adresse de secours de code

et ensuite, nous envoyons le contenu du registre de la hache au registre DS.

Après cela, le registre DS contiendra l'adresse du segment de données. L'adresse DS: 0000H contiendra le symbole H. Je suppose que vous connaissez des segments et des compensations.

L'adresse est composée de deux composants<Сегмент>:<Смещение>Où segment est 2 octets et offset - 2 octets. Il s'avère 4 octets pour accéder à n'importe quel emplacement de mémoire.

mOV AH, 09H
MOV dx, décalé hellomsg
Int 21h.

Ici, nous sommes dans le registre AH, écrivez le numéro 09H - le numéro de la 21e fonction d'interruption, qui affiche une chaîne à l'écran.

Dans la ligne suivante, nous écrivons l'adresse (embarras) au début de notre ligne dans le registre DX.

Ensuite, nous appelons l'interruption 21H est l'interruption des fonctions DOS. Interruption - lorsque le programme étant exécuté est interrompu et le programme d'interruption commence. Par numéro d'interruption, l'adresse du sous-programme DOS est déterminée, qui affiche la chaîne de caractères à l'écran.

Vous aurez probablement une question: pourquoi écrivons-nous le numéro de la fonction 09h dans le registre AH? Et pourquoi le décalage de la chaîne est-il écrit au registre DX?
La réponse est simple: pour chaque fonction, des registres spécifiques contenant des données d'entrée pour cette fonction sont définis. Voir quels registres sont nécessaires des fonctions spécifiques que vous pouvez dans l'aide »e.

mOV AX, 4C00H
Int 21h.

mOV AX, 4C00H - Nous envoyons un numéro de fonction au registre à la hache. Fonction 4C00H - Quittez le programme.

int 21h - effectuer une interruption (effectivement sortir)

la fin est la fin du programme.

Après la fin de la directive, le compilateur ignore tout, afin que vous puissiez tout écrire, n'importe quoi :)

Si vous lisez à la fin, vous êtes un héros!

Maiko G.V. Assembleur pour IBM PC: - M.: "Business Inform", "Sirin" 1999 - 212 p.



Avez-vous aimé l'article? Partagez-le