ΕΝΤ 3

Διακοπή κλήσης 3 (#BP, σημείο διακοπής)

8086

int 3

CD ib

INT imm8

Διακοπή κλήσης imm8

8086

int 13

ΣΕ

Διακοπή κλήσης 4 (#OF, υπερχείλιση) εάν EFLAGS.OF=1

8086

σε

Περιγραφή:

Ομάδα ΕΝΤ 3προορίζεται για τη δημιουργία διακοπής 3 και είναι πανομοιότυπη με την εντολή INT n στην περιγραφή της λειτουργίας, με τη διαφορά ότι ο αριθμός διακοπής δεν υπάρχει άμεσα στον κωδικό πρόσβασης εδώ, αλλά έχει οριστεί σιωπηρά στο 3.

Αυτή η διακοπή προορίζεται να χρησιμοποιηθεί από έναν εντοπισμό σφαλμάτων που τοποθετεί μια ειδική εντολή ενός byte ΕΝΤ 3(κωδικός CCh) αντί για το πρώτο byte εντολών ή αντί για εντολές ενός byte.

Υπάρχει ένας δεύτερος τρόπος να καλέσετε αυτήν τη διακοπή χρησιμοποιώντας τον κωδικό δύο byte INT 3 (κωδικός CD03h). Ωστόσο αυτή τη μέθοδοΔεν χρησιμοποιούνται στην πράξη, όλοι οι x86 assemblers ερμηνεύουν τα μνημονικά από προεπιλογή ΕΝΤ 3ως εντολή ενός byte με τον κωδικό CCh (αλλά αυτό δεν αποκλείει τη δυνατότητα μη αυτόματης προγραμματισμού ενός κώδικα δύο byte). Εκτός από το μέγεθος του κώδικα, η επεξεργασία των εντολών ενός και δύο byte είναι επίσης διαφορετική. ΕΝΤ 3. Μια διακοπή που δημιουργείται από μια εντολή ενός byte στη λειτουργία EV86 (CR4.VME = 1) δεν ανακατευθύνεται από τον χάρτη ανακατεύθυνσης διακοπών (όπως περιγράφεται για τη λειτουργία 2 , λειτουργία 3 , λειτουργία 5) και αντιμετωπίζεται πάντα από τον χειριστή προστατευμένης λειτουργίας μέσω έναν περιγραφέα στον πίνακα IDT. Επιπλέον, στη λειτουργία V86, δεν εκτελούνται έλεγχοι πεδίου IOPL για αυτήν τη διακοπή και, κατά συνέπεια, δεν μπορεί να δημιουργηθεί σφάλμα γενικής προστασίας #GP όταν το EFLAGS.IOPL< 3, то есть однобайтная команда не является IOPL-чувствительной .

Λειτουργία:

Ο αλγόριθμος που παρουσιάζεται εδώ περιγράφει όχι μόνο τη συμπεριφορά του επεξεργαστή κατά την εκτέλεση μιας εντολής ΕΝΤ 3εξωτερική διακοπή ή δημιουργία εξαίρεσης.

ΜΕΤΑ ΠΑΤΕ ΠΡΑΓΜΑΤΙΚΗ-ΔΙΕΥΘΥΝΣΗ-ΛΕΙΤΟΥΡΓΙΑ;

IF (EFLAGS.VM = 1 ΚΑΙ EFLAGS.IOPL< 3 AND

(CR4.VME = 0 Ή CR4.VME = 1 ΚΑΙ IRB[n] = 1)

) (* IRB[n] είναι το bit που αντιστοιχεί στη διακοπή n στον χάρτη ανακατεύθυνσης διακοπής *)

#GP(0); (Διακοπή λογισμικού INT n σε λειτουργία: (1) V86 στο EFLAGS.IOPL< 3, (2) EV86 Режим 2 *)

ΑΛΛΟΥ (* Προστατευμένη λειτουργία ή λειτουργία V86/EV86 *)

IF (EFLAGS.VM = 1 ΚΑΙ CR4.VME = 1 ΚΑΙ

(INT n) ΚΑΙ IRB[n] = 0)

ΑΛΛΟ ΠΑΡΑ PROTECTED-MODE; (* Διακοπές υλικού, εξαιρέσεις, το λογισμικό διακόπτει το INT n σε λειτουργία: (1) Προστατευμένη λειτουργία, (2) V86 με EFLAGS.IOPL = 3, (3) EV86 Λειτουργία 1 ή Λειτουργία 4 *)

ΠΡΑΓΜΑΤΙΚΗ-ΔΙΕΥΘΥΝΣΕΙΣ-ΛΕΙΤΟΥΡΓΙΑ:

IF ((Αριθμός διακοπής * 4) + 3 εκτός τμήματος κατά την πρόσβαση στον πίνακα διανυσμάτων διακοπής IVT) ΤΟΤΕ #GP; FI;

IF (Δεν υπάρχει χώρος στη στοίβα για 6 byte) ΤΟΤΕ #SS; FI;

EFLAGS.IF = 0; (* Επαναφορά σημαίας διακοπής *)

EFLAGS.TF = 0; (* Επαναφορά σημαίας παγίδας *)

EFLAGS.AC = 0; (* Επαναφορά σημαία λειτουργίας ελέγχου ευθυγράμμισης *)

CS = IVT[Αριθμός διακοπής * 4].επιλογέας;

EIP = IVT[Αριθμός διακοπής * 4].offset ΚΑΙ 0x0000FFFFh;

(* Συνέχεια σε λειτουργία πραγματικής διευθυνσιοδότησης... *)

EV86-MODE: (* CR0.PE = 1, EFLAGS.VM = 1, CR4.VME = 1, λειτουργία EV86 - διακοπή λογισμικού INT n, με IRB[n] = 0 - Λειτουργία 3 ή Λειτουργία 5 *)

IF (Η στοίβα εργασιών V86 δεν έχει χώρο για 6 byte) ΤΟΤΕ #SS(0); FI;

tempFLAGS = FLAGS;

tempFLAGS.NT = 0;

ΤΟΤΕ EFLAGS.IF = 0; (* Σημαία ενεργοποίησης επαναφοράς διακοπής *)

tempFLAGS.IF = EFLAGS.VIF;

EFLAGS.VIF = 0; (* Επαναφορά σημαίας εικονικής διακοπής *)

EFLAGS.TF = 0; (* Επαναφορά σημαίας παγίδας *)

Push(tempFLAGS);

(* Δεν υπάρχουν κωδικοί σφάλματος στη στοίβα *)

CS = IVT_V86[Αριθμός διακοπής * 4].επιλογέας; (* Ο διανυσματικός πίνακας διακοπής IVT_V86 βρίσκεται στην αρχή του χώρου διευθύνσεων εργασιών V86 *)

EIP = IVT_V86[Αριθμός διακοπής * 4].offset ΚΑΙ 0x0000FFFFh; (* τα ανώτερα 16-bit του καταχωρητή EIP έχουν οριστεί σε μηδέν *)

(* Συνέχεια σε λειτουργία EV86 ... *)

ΠΡΟΣΤΑΤΕΥΤΗ ΛΕΙΤΟΥΡΓΙΑ: (* CR0.PE = 1, Διακοπές υλικού, εξαιρέσεις, το λογισμικό διακόπτει το INT n στη λειτουργία: (1) Προστατευμένη λειτουργία, (2) V86 με EFLAGS.IOPL = 3, (3) Λειτουργία EV86 1 ή Λειτουργία 4 *)

ΑΝ ((αριθμός διακοπής * 8) + 7 δεν εμπίπτει στον πίνακα IDT) ΤΟΤΕ #GP(αριθμός διακοπής * 8 + 2 + EXT); FI;

(* Στο εξής, στις παραμέτρους του κωδικού σφάλματος, ο όρος +2 σημαίνει τη ρύθμιση του bit IDT του κωδικού σφάλματος και ο όρος +EXT σημαίνει τη ρύθμιση του bit EXT του κωδικού σφάλματος σύμφωνα με το αν η διακοπή που προκάλεσε το σφάλμα ήταν λογισμικό EXT = 0 ή εξωτερικό EXT = 1 * )

Το byte AR του περιγραφέα πρέπει να προσδιορίζει την πύλη διακοπής, την πύλη παγίδευσης ή την πύλη εργασιών, διαφορετικά #GP(αριθμός διακοπής * 8 + 2 + EXT);

IF (Διακοπή λογισμικού ή εξαίρεση) (* δηλ. μία από τις περιπτώσεις INT n, INT 3, INT01, BOUND ή INTO *)

IF (CPL > Gateway DPL)

#GP(αριθμός διακοπής * 8 + 2); (* CR0.PE = 1, Gateway DPL< CPL, программное прерывание *)

Η πύλη πρέπει να υπάρχει διαφορετικά #NP(αριθμός διακοπής * 8 + 2 + EXT);

IF (Task Gateway)

ΜΕΤΑ ΠΑΤΕ TASK-GATE;

ΠΑΩ ΣΕ ΠΑΓΙΔΑ-Η-ΜΕΣΑ-ΠΥΛΗ; (* CR0.PE = 1, διακοπή ή παγίδευση πύλης *)

TRAP-OR-INT-GATE: (* Προστατευμένη λειτουργία ή λειτουργία V86/EV86, πύλη παγίδευσης ή διακοπής *)

Έλεγχος του νέου επιλογέα CS που καθορίζεται στον περιγραφέα πύλης και του αντίστοιχου περιγραφέα του από LDT ή GDT:

Ο επιλογέας πρέπει να είναι μη μηδενικός, διαφορετικά #GP(EXT);

Ο δείκτης επιλογής πρέπει να εμπίπτει στον πίνακα περιγραφών, διαφορετικά #GP(επιλογέας + EXT);

Ο επιλεγμένος περιγραφέας πρέπει να είναι ένας περιγραφέας τμήματος κώδικα, διαφορετικά #GP(επιλογέας + EXT).

Το τμήμα πρέπει να υπάρχει (P = 1), διαφορετικά #NP(επιλογέας + EXT);

IF (Το τμήμα κώδικα δεν είναι συνεπές) ΚΑΙ (DPL του τμήματος κώδικα< CPL)

IF EFLAGS.VM = 0

ΜΕΤΑ ΠΑΤΕ INT-TO-INTER-PRIV; (* CR0.PE = 1, EFLAGS.VM = 0, πύλη διακοπής ή παγίδευσης, αναντιστοιχία τμήμα κώδικα, τμήμα κώδικα DPL< CPL *)

ELSE(*EFLAGS.VM=1*)

IF (DPL νέου τμήματος κώδικα ≠ 0) ΤΟΤΕ #GP(Επιλογέας τμήματος κώδικα + EXT); FI;

ΠΑΩ ΣΕ INT-FROM-V86-MODE;(* CR0.PE = 1, EFLAGS.VM = 1, πύλη διακοπής ή παγίδευσης, τμήμα κωδικού DPL = 0, CPL = 3 *)

ΑΛΛΟΥ (* CR0.PE = 1, πύλη διακοπής ή παγίδευσης, αντιστοιχισμένο τμήμα κώδικα ή αναντιστοιχία τμήμα κώδικα με DPL = CPL *)

ΑΝ EFLAGS.VM = 1 ΤΟΤΕ #GP(Code Segment Selector + EXT); FI;

IF ((τμήμα κώδικα με διαπραγμάτευση) Ή (τμήμα κώδικα DPL = CPL))

ΜΕΤΑ ΠΑΤΕ INT-TO-INTRA-PRIV; (* CR0.PE = 1, πύλη διακοπής ή παγίδευσης, τμήμα κωδικού DPL ≤ CPL για αντιστοιχισμένο τμήμα, τμήμα κώδικα DPL = CPL για ασυνεπές τμήμα *)

ELSE #GP(Επιλογέας τμήματος κώδικα + EXT); (* DPL > CPL για αντιστοιχισμένο τμήμα ή DPL ≠ CPL για μη αντιστοιχισμένο τμήμα *)

INT-TO-INTER-PRIV: (* Προστατευμένη λειτουργία, πύλη διακοπής ή παγίδευσης, αναντιστοιχία τμήματος κώδικα, τμήμα κώδικα DPL< CPL *)

IF (Τρέχον TSS 32-bit)

TSSstackAddress = (νέο τμήμα κώδικα DPL * 8) + 4

IF ((TSSstackAddress + 5) > Όριο TSS) (* (TSSstackAddress + 7) >

NewsSS = [Base TSS + TSSstackAddress + 4]; (*φόρτωση 2 byte*)

(* Φορτώνονται 4 byte *)

ΑΛΛΟΥ (* Τρέχον TSS 16-bit *)

TSSstackAddress = (νέο τμήμα κώδικα DPL * 4) + 2

IF ((TSSstackAddress + 3) > Όριο TSS) (* (TSSstackAddress + 4) > Όριο TSS - για ορισμένα μοντέλα επεξεργαστών *)

ΜΕΤΑ #TS (Τρέχον επιλογέας TSS + EXT);

NewESP = [Base TSS + TSSstackAddress]; (*φόρτωση 2 byte*)

NewsSS = [Base TSS + TSSstackAddress + 2]; (*φόρτωση 2 byte*)

Το RPL του επιλογέα πρέπει να είναι ίσο με το DPL του νέου τμήματος κωδικού, αλλιώς #TS(SS επιλογέας + EXT).

Το DPL του τμήματος στοίβας πρέπει να είναι ίσο με το DPL του νέου τμήματος κώδικα, διαφορετικά #TS(SS επιλογέας + EXT).

IF (πύλη 32 bit)

ΤΟΤΕ Η νέα στοίβα πρέπει να έχει χώρο για 20 byte (24 byte εάν υπάρχει κωδικός σφάλματος), διαφορετικά #SS(EXT)

ΑΛΛΑ Η νέα στοίβα πρέπει να έχει χώρο για 10 byte (12 byte εάν υπάρχει κωδικός σφάλματος), διαφορετικά #SS(EXT)

SS:ESP = TSS(NewSS:NewESP); (* Λήψη νέων τιμών SS και eSP από το TSS *)

IF (πύλη 32 bit)

ΕΠΕΙΤΑ

ELSE CS:IP = Gate(SELECTOR:OFFSET);

Φορτώστε τον περιγραφέα SS στο κρυφό τμήμα του καταχωρητή SS.

IF (πύλη 32 bit)

Push(Μακρύς δείκτης προς την παλιά στοίβα - SS:ESP);

Push(Μεγάλος δείκτης στο σημείο επιστροφής - CS:EIP); (*3 λέξεις συμπληρώνονται σε 4*)

Push(Κωδικός σφάλματος);

Push(Μεγάλος δείκτης στην παλιά στοίβα - SS:SP); (*2 λέξεις*)

Push(Μεγάλος δείκτης στο σημείο επιστροφής - CS:IP); (*2 λέξεις*)

Push(Κωδικός σφάλματος);

CPL = DPL του νέου τμήματος κώδικα.

IF (Πύλη διακοπής) ΤΟΤΕ EFLAGS.IF = 0 FI; (* Επαναφορά σημαίας διακοπής *)

EFLAGS.RF = 0;

(* Συνεχίστε την εκτέλεση σε προστατευμένη λειτουργία σε υψηλό επίπεδο προνομίων... *)

INT-FROM-V86-MODE: (* Λειτουργία V86/EV86, διακοπή ή παγίδευση πύλης, DPL = 0, CPL = 3 *)

(* Το τρέχον TSS είναι πάντα 32-bit στη λειτουργία V86 *)

IF (όριο TSS< 9) (*Όριο TSS< 11 - для некоторых моделей процессоров *)

ΜΕΤΑ #TS (Τρέχον επιλογέας TSS + EXT);

NewsSS = [Βάση TSS + 8]; (*φόρτωση 2 byte*)

NewESP = [Βάση TSS + 4]; (* Φορτώνονται 4 byte *)

Έλεγχος του επιλογέα του νέου τμήματος στοίβας NewsSS και του αντίστοιχου περιγραφέα του από LDT ή GDT:

Ο επιλογέας πρέπει να είναι μη μηδενικός, διαφορετικά #TS(EXT);

Ο δείκτης επιλογέα πρέπει να εμπίπτει στον πίνακα περιγραφών, διαφορετικά #TS(SS επιλογέας + EXT);

Το RPL του επιλογέα πρέπει να είναι μηδέν, διαφορετικά #TS(SS επιλογέας + EXT);

Το DPL του τμήματος στοίβας πρέπει να είναι μηδέν, διαφορετικά #TS(SS επιλογέας + EXT);

Ο περιγραφέας πρέπει να έχει τη μορφή ενός εγγράψιμου περιγραφέα τμήματος δεδομένων (W = 1), διαφορετικά #TS(SS επιλογέας + EXT).

Το τμήμα πρέπει να υπάρχει (P = 1), διαφορετικά #SS(SS επιλογέας + EXT);

IF (πύλη 32 bit)

Η νέα στοίβα πρέπει να έχει χώρο για 36 byte (40 byte εάν υπάρχει κωδικός σφάλματος), διαφορετικά #SS(EXT)

Ο νέος δείκτης εντολών πρέπει να εμπίπτει στο νέο τμήμα κώδικα, διαφορετικά #GP(EXT); (* ο δείκτης εντολών καθορίζεται από την τιμή του πεδίου OFFSET από τον περιγραφέα πύλης *)

TempEflags = EFLAGS;

EFLAGS.VM = 0; (* Ο επεξεργαστής βγαίνει από τη λειτουργία V86 για να χειριστεί τη διακοπή σε προστατευμένη λειτουργία *)

IF (Πύλη διακοπής)

ΤΟΤΕ EFLAGS.IF = 0;

CPL=0; (* Μετάβαση στο επίπεδο προνομίων μηδέν *)

SS:ESP = TSS(NewSS:NewESP); (* Φόρτωση τιμών SS0 και ESP0 από το TSS *)

Push(GS);

Push(FS); (*επεκτείνεται σε δύο λέξεις*)

Push(DS); (*επεκτείνεται σε δύο λέξεις*)

Push(ES); (*επεκτείνεται σε δύο λέξεις*)

GS = 0; (* Οι καταχωρητές τμημάτων μηδενίζονται. Η επακόλουθη χρήση μηδενικών επιλογέων σε προστατευμένη λειτουργία δεν επιτρέπεται *)

Push(TempSS); (*επεκτείνεται σε δύο λέξεις*)

Push(TempEflags);

Push(CS); (*επεκτείνεται σε δύο λέξεις*)

Push(Κωδικός σφάλματος); (* Εάν υπάρχει, 4 byte *)

CS:EIP = Πύλη (SELECTOR:OFFSET); (* Επιλογέας φόρτωσης: μετατόπιση από λαβή πύλης 32 bit *)

ELSE (*16-bit gateway*)

Η νέα στοίβα πρέπει να έχει χώρο για 18 byte (20 byte εάν υπάρχει κωδικός σφάλματος), διαφορετικά #SS(EXT)

(* Η αποθήκευση τιμών καταχωρητή 16-bit στη στοίβα είναι παρόμοια με μια πύλη 32-bit *)

(* Δεν θα είναι δυνατή η επιστροφή από μια διακοπή με μια εντολή IRET στη λειτουργία V86 από ένα τμήμα 16 bit, καθώς η σημαία VM δεν θα αποθηκευτεί στη στοίβα και δεν θα αποκατασταθεί από την εικόνα EFLAGS κατά την επιστροφή *)

(* Συνεχίστε την εκτέλεση σε προστατευμένη λειτουργία με επίπεδο προνομίου μηδέν... *)

INT-TO-INTRA-PRIV: (* CR0.PE = 1, DPL = CPL ή αντιστοιχισμένο τμήμα με DPL ≤ CPL *)

IF (πύλη 32 bit)

ΤΟΤΕ Η νέα στοίβα πρέπει να έχει χώρο για 12 byte (16 byte εάν υπάρχει κωδικός σφάλματος), διαφορετικά #SS(EXT)

ΑΛΛΑ Η νέα στοίβα πρέπει να έχει χώρο για 6 byte (8 byte εάν υπάρχει κωδικός σφάλματος), διαφορετικά #SS(EXT)

Ο νέος δείκτης εντολών πρέπει να εμπίπτει στο νέο τμήμα κώδικα, διαφορετικά #GP(EXT);

IF (πύλη 32 bit)

Push (Μεγάλος δείκτης στο σημείο επιστροφής). (*3 λέξεις συμπληρώνονται σε 4*)

CS:EIP = Πύλη (SELECTOR:OFFSET); (* Επιλογέας φόρτωσης: μετατόπιση από λαβή πύλης 32 bit *)

Push(Κωδικός σφάλματος); (* Εάν υπάρχει, 4 byte *)

Push (Μεγάλος δείκτης στο σημείο επιστροφής). (*2 λέξεις*)

CS:IP = Πύλη (SELECTOR:OFFSET); (* Επιλογέας φόρτωσης: μετατόπιση από τον περιγραφέα πύλης 16-bit *)

Push(Κωδικός σφάλματος); (* Εάν υπάρχει, 2 byte *)

Φορτώστε τον περιγραφέα CS στο κρυφό τμήμα του καταχωρητή CS.

IF (Πύλη διακοπής) ΤΟΤΕ EFLAGS.IF = 0; FI;

(* Συνεχίστε την εκτέλεση σε προστατευμένη λειτουργία χωρίς αλλαγή του επιπέδου προνομίων... *)

TASK-GATE: (* CR0.PE = 1, πύλη εργασιών *)

Έλεγχος του επιλογέα TSS από τη λαβή της πύλης εργασιών:

Ο επιλογέας πρέπει να καθορίσει GDT (BIt TI = 0), διαφορετικά #GP(επιλογέας TSS + EXT).

Ο δείκτης επιλογέα πρέπει να εμπίπτει στον πίνακα GDT, διαφορετικά #GP(επιλογέας TSS + EXT).

Έλεγχος του αντίστοιχου περιγραφέα TSS για τον επιλεγμένο επιλογέα:

Ο περιγραφέας TSS πρέπει να έχει ελεύθερο τύπο TSS (TYPE.B = 0), διαφορετικά #GP(επιλογέας TSS + EXT).

Πρέπει να υπάρχει TSS (P = 1), διαφορετικά #NP(επιλογέας TSS + EXT);

SWITCH-TASKS (Με συνημμένο) στο TSS. (* εδώ "Με ένθεση" σημαίνει το γεγονός ότι όταν αρχικοποιείται το περιβάλλον νέα εργασίαΗ σημαία EFLAGS.NT = 1 θα οριστεί και ο επιλογέας TSS της διακοπείσας (παλιάς) εργασίας θα αντιγραφεί στο πεδίο LINK του τμήματος TSS - βλέπε Διεύθυνση και πολλαπλές εργασίες: Υποστήριξη πολλαπλών εργασιών *)

IF (Η διακοπή είναι μια ειδική κατάσταση με κωδικό σφάλματος)

Πρέπει να υπάρχει χώρος στη στοίβα για τον κωδικό σφάλματος, διαφορετικά #SS(EXT);

push(κωδικός σφάλματος);

Ο δείκτης εντολής EIP πρέπει να εμπίπτει στο τμήμα CS, αλλιώς #GP(EXT).

(* Η φόρτωση ενός νέου πλαισίου εργασιών συνοδεύεται από πρόσθετους ελέγχους, όπως περιγράφεται στην ενότητα Διεύθυνση και πολλαπλές εργασίες: Υποστηρίζει η λειτουργία πολλαπλών εργασιών *)

(* Συνέχεια στο πλαίσιο της νέας εργασίας... *)

Εξαιρέσεις προστατευμένων λειτουργιών:

ΕΝΤ 3, αλλά και όταν δημιουργείται οποιαδήποτε εξωτερική διακοπή ή εξαίρεση. Κομμάτι ΕΞΩΤστον κωδικό σφάλματος εξωτερικής διακοπής).

  • περιγραφέας διάνυσμα(ευρετήριο) της διακοπής δεν βρίσκεται εντός του πίνακα περιγραφής διακοπής (IDT) .
  • λαβή που αντιστοιχεί σε αυτήν που υποβάλλεται σε επεξεργασία διάνυσμα(ευρετήριο) μιας διακοπής, δεν είναι λαβή σε πύλη παγίδας, πύλη διακοπής ή πύλη εργασιών.
  • προκύπτει μια διακοπή λογισμικού ή μια εξαίρεση λογισμικού (δηλαδή, μια από τις περιπτώσεις: INT n , INT 3 , INT01, BOUND ή INTO) και τρέχον επίπεδο προνομίων(CPL) περισσότερες εργασίες επίπεδο προνομίων(DPL) περιγραφέας πύληςαπό τον πίνακα IDT −
  • επιλογέα τμήματος στην αντίστοιχη επεξεργασία διάνυσμα(ευρετήριο) της λαβής διακοπής προς την πύλη παγίδευσης, την πύλη διακοπής ή την πύλη εργασιών είναι μηδενικός επιλογέας.
  • ο δείκτης του επιλογέα τμήματος του περιγραφέα πύλης παγίδευσης ή του περιγραφέα πύλης διακοπής δεν εμπίπτει στα όρια του αντίστοιχου πίνακα περιγραφών.
  • Ο δείκτης επιλογέα TSS από τον περιγραφέα της πύλης εργασίας που αντιστοιχεί σε διακοπές είναι εκτός ορίων καθολικός πίνακας περιγραφών(GDT);
  • περιγραφέαςΤο νέο τμήμα κώδικα δεν είναι περιγραφέας τμήματος κώδικα.
  • (DPL) το νέο τμήμα κώδικα με διαπραγμάτευση είναι μεγαλύτερο τρέχον επίπεδο προνομίωνεργασίες (CPL) -
  • χειριστεί το επίπεδο προνομίων(DPL) του νέου αταίριαστου τμήματος κώδικα δεν ισούται με τρέχον επίπεδο προνομίωνεργασίες (CPL) -
  • ο επιλογέας TSS από τον περιγραφέα της πύλης εργασιών που αντιστοιχεί στη διακοπή δείχνει σε τοπικός πίνακας περιγραφών(LDT);
  • η λαβή TSS της νέας εργασίας επισημαίνεται ως απασχολημένος- TYPE.B ≠ 1.
  • τη διεύθυνση για την οποία πρέπει να διαβαστεί η νέα τιμή δείκτη στοίβας(SS:eSP), εκτός τμήματος TSS ;
  • ο επιλογέας του νέου τμήματος στοίβας είναι μηδενικός επιλογέας.
  • ο δείκτης επιλογής του νέου τμήματος στοίβας δεν εμπίπτει στον αντίστοιχο πίνακα περιγραφών.
  • ζητήθηκε επίπεδο προνομίουΟ επιλογέας (RPL) του νέου τμήματος στοίβας δεν είναι ίσος με (DPL) ενός νέου τμήματος κώδικα -
  • χειριστεί το επίπεδο προνομίων(DPL) του τμήματος νέας στοίβας δεν ισούται με χειριστεί το επίπεδο προνομίων(DPL) ενός νέου τμήματος κώδικα -
  • το νέο τμήμα στοίβας δεν είναι εγγράψιμο τμήμα δεδομένων -
  • η αντίστοιχη λαβή διακοπής στην πύλη παγίδας, πύλη διακοπής, πύλη εργασιών ή λαβή TSS επισημαίνεται ως απών(το bit P του περιγραφέα είναι σαφές).
  • νέο τμήμα κώδικα δεν υπάρχει ( bit P ο περιγραφέας τμήματος επαναφέρεται).
  • κατά την εγγραφή στη στοίβα (συμπεριλαμβανομένης της νέας στοίβας εάν πραγματοποιήθηκε αλλαγή στοίβας) των τιμών διευθύνσεις επιστροφής, δείκτη στοίβας, σημαίεςή έναν κωδικό σφάλματος, το τμήμα στοίβας είναι εκτός ορίων.
  • το νέο τμήμα στοίβας δεν υπάρχει (το bit P του περιγραφέα τμήματος είναι σαφές).

Ειδικές καταστάσεις πραγματικής λειτουργίας διευθυνσιοδότησης:

Η λίστα εξαιρέσεων που παρουσιάζεται εδώ χαρακτηρίζει τη συμπεριφορά του επεξεργαστή όχι μόνο κατά την εκτέλεση μιας εντολής ΕΝΤ 3, αλλά και όταν δημιουργείται οποιαδήποτε εξωτερική διακοπή ή εξαίρεση.

Ειδικές καταστάσεις λειτουργίας V86:

Η λίστα εξαιρέσεων που παρουσιάζεται εδώ χαρακτηρίζει τη συμπεριφορά του επεξεργαστή όχι μόνο κατά την εκτέλεση μιας εντολής ΕΝΤ 3, αλλά και όταν δημιουργείται οποιαδήποτε εξωτερική διακοπή ή εξαίρεση. Κομμάτι ΕΞΩΤστον κωδικό σφάλματος χρησιμοποιείται για να υποδείξει ένα συμβάν εκτός του προγράμματος που έχει διακοπεί (

Οι συναρμολογητές MASM, TASM και WASM διαφέρουν μεταξύ τους. Ωστόσο, η δημιουργία απλών προγραμμάτων για αυτά δεν έχει ουσιαστικά καμία διαφορά, με εξαίρεση τη συναρμολόγηση και τη σύνδεση.

Το πρώτο μας πρόγραμμα λοιπόν για MASM, TASM και WASM, που βγάζει Αγγλική επιστολή"A" στην τρέχουσα θέση του δρομέα, δηλαδή στα αριστερά πάνω γωνίαοθόνη:

Μοντέλο μικροσκοπικό .code ORG 100h έναρξη: MOV AH,2 MOV DL,41h INT 21h INT 20h END start επεξεργαστής κειμένου- για παράδειγμα, σε ένα NOTEBOOK (NotePad) από τα WINDOWS (αλλά όχι στο Word και όχι σε άλλο "φανταχτερό"). Ωστόσο, προτείνω ένα "προηγμένο" πρόγραμμα επεξεργασίας κειμένου με επισήμανση σύνταξης όπως το PSPad (βλ. ενότητα ). Στη συνέχεια αποθηκεύουμε αυτό το αρχείο με την επέκταση .asm, για παράδειγμα, στο φάκελο MYPROG. Ας ονομάσουμε το αρχείο atest. Έτσι πήραμε: C:\MYPROG\test.asm.

ΣΗΜΕΙΩΣΗ
Σημειώστε ότι στην πρώτη εντολή γράψαμε 2 αντί για 02h. Οι MASM, TASM και WASM, όπως το Emu8086, επιτρέπουν τέτοιες "ελευθερίες". Αν και μπορείτε να γράψετε 02h - δεν θα υπάρξει σφάλμα.

Επεξηγήσεις για το πρόγραμμα:

.μοντέλο μικροσκοπικό- 1η γραμμή. Η οδηγία .model ορίζει το μοντέλο μνήμης για έναν συγκεκριμένο τύπο αρχείου. Στην περίπτωσή μας, αυτό είναι ένα αρχείο COM, επομένως επιλέγουμε το μικροσκοπικό μοντέλο, το οποίο συνδυάζει τμήματα κώδικα, δεδομένων και στοίβας. Το μικροσκοπικό μοντέλο έχει σχεδιαστεί για τη δημιουργία αρχείων COM.

.κώδικας- 2η γραμμή. Αυτή η οδηγία ξεκινά ένα τμήμα κώδικα.

ORG 100h- 3η γραμμή. Αυτή η εντολή ορίζει τον μετρητή προγράμματος σε 100h, επειδή κατά τη φόρτωση ενός αρχείου COM στη μνήμη, το DOS εκχωρεί τα πρώτα 256 byte για το μπλοκ δεδομένων PSP ( δεκαδικός αριθμός 256 ισούται με δεκαεξαδικό 100h). Ο κωδικός προγράμματος βρίσκεται μόνο μετά από αυτό το μπλοκ. Όλα τα προγράμματα που μεταγλωττίζονται σε αρχεία COM πρέπει να ξεκινούν με αυτήν την οδηγία.

έναρξη: MOV AH, 02h- 4η γραμμή. Η ετικέτα έναρξης τοποθετείται πριν από την πρώτη εντολή στο πρόγραμμα και θα χρησιμοποιηθεί στην οδηγία ΤΕΛΟΣ για να υποδείξει με ποια εντολή ξεκινά το πρόγραμμα. Η εντολή MOV τοποθετεί την τιμή του δεύτερου τελεστή στον πρώτο τελεστή. Δηλαδή, η τιμή 02h τοποθετείται στον καταχωρητή AH. Σε τι χρησιμεύει; Το 02h είναι μια συνάρτηση DOS που εκτυπώνει έναν χαρακτήρα στην οθόνη. Γράφουμε ένα πρόγραμμα για το DOS, οπότε χρησιμοποιούμε τις εντολές αυτού λειτουργικό σύστημα(OS). Και γράφουμε αυτή τη συνάρτηση (ή μάλλον τον αριθμό της) στον καταχωρητή AH, επειδή η διακοπή 21h χρησιμοποιεί αυτόν τον συγκεκριμένο καταχωρητή.

MOV DL, 41h- 5η γραμμή. Ο κωδικός χαρακτήρα "A" εισάγεται στον καταχωρητή DL. Ο κωδικός χαρακτήρων ASCII για το "A" είναι ο αριθμός 41h.

INT 21h- 6η γραμμή. Αυτή είναι η ίδια η διακοπή 21h - μια εντολή που καλεί τη συνάρτηση συστήματος DOS που καθορίζεται στον καταχωρητή AH (στο παράδειγμά μας, αυτή είναι η συνάρτηση 02h). Η εντολή INT 21h είναι το κύριο μέσο αλληλεπίδρασης μεταξύ των προγραμμάτων και του λειτουργικού συστήματος.

INT 20h- 7η γραμμή. Αυτή είναι μια διακοπή που λέει στο λειτουργικό σύστημα να βγει από το πρόγραμμα και να μεταφέρει τον έλεγχο στην εφαρμογή της κονσόλας. Σε περίπτωση που το πρόγραμμα έχει ήδη μεταγλωττιστεί και εκτελεστεί από το λειτουργικό σύστημα, η εντολή INT 20h θα μας επιστρέψει στο λειτουργικό σύστημα (για παράδειγμα, στο DOS).

ΤΕΛΟΣ εκκίνησης- 8η γραμμή. Η οδηγία ΤΕΛΟΣ τερματίζει το πρόγραμμα, υποδεικνύοντας ταυτόχρονα από ποια ετικέτα πρέπει να ξεκινήσει η εκτέλεσή του.

Τι είναι ένας συναρμολογητής

Η Assembler είναι μια γλώσσα προγραμματισμού χαμηλού επιπέδου. Κάθε επεξεργαστής έχει το δικό του assembler. Με τον προγραμματισμό σε assembler εργάζεστε απευθείας με το υλικό του υπολογιστή. Το κείμενο προέλευσης της γλώσσας συναρμολόγησης αποτελείται από οδηγίες (μνημονικά) που, μετά τη μεταγλώττιση, μετατρέπονται σε κώδικες οδηγιών επεξεργαστή.

Η ανάπτυξη προγραμμάτων σε assembler είναι πολύ δύσκολο πράγμα. Σε αντάλλαγμα για τον χρόνο που ξοδεύετε, έχετε ένα αποτελεσματικό πρόγραμμα. Τα προγράμματα Assembler γράφονται όταν κάθε κύκλος του επεξεργαστή είναι σημαντικός. Στο assembler δίνεις συγκεκριμένες εντολές στον επεξεργαστή και όχι περιττά σκουπίδια. Αυτό είναι που εξασφαλίζει την υψηλή ταχύτητα εκτέλεσης του προγράμματός σας.

Για να χρησιμοποιήσετε σωστά το assembler, πρέπει να γνωρίζετε το μοντέλο προγράμματος του συστήματος μικροεπεξεργαστή. Από την άποψη ενός προγραμματιστή, ένα σύστημα μικροεπεξεργαστή αποτελείται από:

  1. μικροεπεξεργαστής
  2. μνήμη
  3. Συσκευές εισόδου/εξόδου.

Το μοντέλο προγραμματισμού περιγράφεται καλά στη βιβλιογραφία.

Σύνταξη συναρμολόγησης

Η γενική μορφή μιας γραμμής προγράμματος σε assembler

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

Πεδίο ετικέτας. Η ετικέτα μπορεί να αποτελείται από σύμβολα και κάτω παύλες. Οι ετικέτες χρησιμοποιούνται σε λειτουργίες άλματος υπό όρους και άνευ όρων.

Πεδίο χειριστή. Αυτό το πεδίο περιέχει την εντολή Mnemonic. Για παράδειγμα μνημονική κιν

Πεδίο τελεστών. Οι τελεστές μπορούν να υπάρχουν μόνο εάν υπάρχει χειριστής (πεδίο χειριστή). Μπορεί να μην υπάρχουν τελεστές ή μπορεί να υπάρχουν αρκετοί. Οι τελεστές μπορεί να είναι δεδομένα στα οποία πρέπει να εκτελέσετε κάποια ενέργεια (αποστολή, προσθήκη κ.λπ.).

Πεδίο σχολίων. Ο σχολιασμός χρειάζεται για τη λεκτική συνοδεία του προγράμματος. Όλα πίσω από το σύμβολο ; θεωρήθηκε ένα σχόλιο.

Το πρώτο πρόγραμμα της γλώσσας assembly

Αυτό το άρθρο θα χρησιμοποιήσει το assembler για τον επεξεργαστή i80x86 και θα χρησιμοποιήσει το ακόλουθο λογισμικό:

  • TASM - Borland Turbo Assembler - Compiler
  • TLINK - Borland Turbo Linker - πρόγραμμα επεξεργασίας συνδέσμων (σύνδεσμος)

Για να είμαστε συγκεκριμένοι, Tasm 2.0.

Κατά παράδοση, το πρώτο μας πρόγραμμα θα τυπώσει τη συμβολοσειρά "Hello world!" στην οθόνη.

αρχείο sample.asm

Μοντέλο μικρό ; Μνήμη model.stack 100h ; Ρύθμιση του stack size.data ; Έναρξη τμήματος δεδομένων προγράμματος HelloMsg DB "Hello World!",13,10,"$" .code ; Έναρξη τμήματος κώδικα mov ax,@DATA ; Μετακίνηση διεύθυνσης τμήματος δεδομένων στον καταχωρητή AX mov ds,ax ; Ορίστε τον καταχωρητή DS στο τμήμα δεδομένων mov ah,09h ; Λειτουργία DOS για εκτύπωση συμβολοσειράς στην οθόνη mov dx,offset HelloMsg ; Ρυθμίστε τη μετατόπιση στην αρχή της συμβολοσειράς int 21h ; Συμβολοσειρά εξόδου mov ax,4C00h ; Λειτουργία εξόδου προγράμματος DOS int 21h ; Έξοδος από το τέλος του προγράμματος

Όπως μπορείτε να δείτε, το πρόγραμμα χωρίζεται σε τμήματα: ένα τμήμα δεδομένων, ένα τμήμα κώδικα και υπάρχει επίσης ένα τμήμα στοίβας.

Ας τα εξετάσουμε όλα με τη σειρά.

Η οδηγία .model small καθορίζει το μοντέλο μνήμης. Το μικρό μοντέλο είναι 1 τμήμα για τον κώδικα, 1 τμήμα για δεδομένα και στοίβα, δηλ. τα δεδομένα και η στοίβα βρίσκονται στο ίδιο τμήμα. Υπάρχουν και άλλα μοντέλα μνήμης, για παράδειγμα: μικροσκοπικό, μεσαίο, συμπαγές. Ανάλογα με το μοντέλο μνήμης που επιλέγετε, τα τμήματα του προγράμματός σας ενδέχεται να επικαλύπτονται ή να έχουν ξεχωριστά τμήματα στη μνήμη.

Η οδηγία .stack 100h ορίζει το μέγεθος της στοίβας. Η στοίβα είναι απαραίτητη για την αποθήκευση ορισμένων πληροφοριών με την επακόλουθη επαναφορά της. Συγκεκριμένα, η στοίβα χρησιμοποιείται για διακοπές. Σε αυτήν την περίπτωση, τα περιεχόμενα του καταχωρητή FLAGS, του καταχωρητή CS και του καταχωρητή IP αποθηκεύονται στη στοίβα. Στη συνέχεια ακολουθεί η εκτέλεση του προγράμματος διακοπής και στη συνέχεια αποκαθίστανται οι τιμές αυτών των καταχωρητών.

  • Ο καταχωρητής FLAGS περιέχει σημάδια που δημιουργούνται μετά την εκτέλεση μιας εντολής από τον επεξεργαστή.
  • Ο καταχωρητής CS (Code Segment) περιέχει τη διεύθυνση του τμήματος κώδικα.
  • Καταχώρηση IP (Instruction Pointer) - δείκτης εντολών. Περιέχει τη διεύθυνση της εντολής που θα εκτελεστεί στη συνέχεια (Διεύθυνση σε σχέση με το τμήμα κώδικα CS).

Περισσότερο Λεπτομερής περιγραφήυπερβαίνει ένα απλό άρθρο.

Η οδηγία .data ορίζει την αρχή του τμήματος δεδομένων του προγράμματός σας. Το τμήμα δεδομένων ορίζει "μεταβλητές", π.χ. υπάρχει κράτηση μνήμης για τα απαραίτητα δεδομένα. Μετά το .data υπάρχει μια γραμμή
HelloMsg DB "Hello World!",13,10,"$"

Εδώ το HelloMsg είναι το συμβολικό όνομα που ταιριάζει με την αρχή της συμβολοσειράς "Hello World!" (χωρίς εισαγωγικά). Δηλαδή, αυτή είναι η διεύθυνση του πρώτου χαρακτήρα της συμβολοσειράς μας σε σχέση με το τμήμα δεδομένων. Η οδηγία DB (Define Byte) ορίζει τη διαθέσιμη περιοχή μνήμης byte προς byte. 13,10 - κωδικοί χαρακτήρων Νέα γραμμήκαι Carriage επιστρέφουν και ο χαρακτήρας $ απαιτείται για να λειτουργήσει σωστά η συνάρτηση DOS 09h. Έτσι, η συμβολοσειρά μας θα καταλαμβάνει 15 byte στη μνήμη.

Η οδηγία .code ορίζει την αρχή του τμήματος κώδικα (CS - Code Segment) του προγράμματος. Ακολουθούν οι γραμμές του προγράμματος που περιέχουν μνημονικές εντολές.

Ας μιλήσουμε για την εντολή mov.

κιν<приёмник>, <источник>

Η εντολή mov είναι μια εντολή κίνησης. Στέλνει τα περιεχόμενα της πηγής στον προορισμό. Οι μεταφορές μπορεί να είναι καταχωρητής-καταχωρητής, καταχωρητής-μνήμη, καταχωρητής μνήμης, αλλά δεν υπάρχει μεταφορά μνήμης-μνήμης, δηλ. όλα περνούν από τα μητρώα του επεξεργαστή.

Για να εργαστείτε με δεδομένα, πρέπει να ρυθμίσετε έναν καταχωρητή τμήματος δεδομένων. Η ρύθμιση είναι ότι γράφουμε τη διεύθυνση του τμήματος δεδομένων @DATA στον καταχωρητή DS (Τμήμα Δεδομένων). Είναι αδύνατο να γράψετε απευθείας τη διεύθυνση σε αυτόν τον καταχωρητή - αυτή είναι η αρχιτεκτονική, επομένως χρησιμοποιούμε τον καταχωρητή AX. Στο AX γράφουμε τη διεύθυνση του τμήματος κώδικα

και μετά στέλνουμε τα περιεχόμενα του καταχωρητή AX στον καταχωρητή DS.

Μετά από αυτό, ο καταχωρητής DS θα περιέχει τη διεύθυνση της αρχής του τμήματος δεδομένων. Η διεύθυνση DS:0000h θα περιέχει τον χαρακτήρα H. Υποθέτω ότι γνωρίζετε για τμήματα και μετατοπίσεις.

Η διεύθυνση αποτελείται από δύο μέρη.<Сегмент>:<Смещение>όπου το τμήμα είναι 2 byte και η μετατόπιση είναι 2 byte. Αποδεικνύονται 4 byte για πρόσβαση σε οποιοδήποτε κελί μνήμης.

mov ah, 09h
mov dx,offset HelloMsg
int 21h

Εδώ γράφουμε τον αριθμό 09h στον καταχωρητή AH - τον αριθμό της συνάρτησης της 21ης ​​διακοπής, που εμφανίζει τη γραμμή στην οθόνη.

Στην επόμενη γραμμή, γράφουμε τη διεύθυνση (αμηχανία) στην αρχή της γραμμής μας στον καταχωρητή DX.

Στη συνέχεια, ονομάζουμε διακοπή 21h - αυτή είναι μια διακοπή για τις λειτουργίες DOS. Διακοπή - όταν διακόπτεται ένα πρόγραμμα που εκτελείται και ξεκινά η εκτέλεση του προγράμματος που διακόπτει. Ο αριθμός διακοπής καθορίζει τη διεύθυνση μιας υπορουτίνας DOS που εκτυπώνει μια σειρά χαρακτήρων στην οθόνη.

Θα έχετε πιθανώς μια ερώτηση: Γιατί γράφουμε τον αριθμό συνάρτησης 09h στον καταχωρητή AH; Και γιατί η μετατόπιση στη γραμμή γράφεται στον καταχωρητή DX;
Η απάντηση είναι απλή: για κάθε συνάρτηση ορίζονται συγκεκριμένοι καταχωρητές που περιέχουν τα δεδομένα εισόδου για αυτή τη συνάρτηση. Μπορείτε να δείτε ποιοι καταχωρητές χρειάζονται για συγκεκριμένες λειτουργίες στη βοήθεια "π.

movax,4C00h
int 21h

mov ax,4C00h - στείλτε τον αριθμό λειτουργίας στον καταχωρητή AX. Λειτουργία 4C00h - έξοδος από το πρόγραμμα.

int 21h - εκτελέστε μια διακοπή (στην πραγματικότητα έξοδο)

τέλος - τέλος προγράμματος.

Μετά την οδηγία τέλους, ο μεταγλωττιστής αγνοεί τα πάντα, οπότε μπορείτε να γράψετε ό,τι θέλετε εκεί :)

Αν έχεις διαβάσει μέχρι το τέλος, τότε είσαι ήρωας!

Maiko G.V. Assembler για IBM PC: - M.: "Business-Inform", "Sirin" 1999 - 212 p.