Muss ich den Fehlercode Pop geschoben von bestimmten Ausnahmen zu stapeln, bevor sie aus dem Interrupt-Handler zurückkehrt?

StackOverflow https://stackoverflow.com/questions/491613

Frage

Ich habe eine idt Tabelle mit 256 Einträgen geladen, die alle auf Ähnliche Handler:

  • für Ausnahmen 8 und 10-14, drücken Sie die Ausnahmenummer (diese Ausnahmen schieben einen Fehlercode automatisch)
  • für die anderen, drücken, um einen „Dummy“ Fehlercode und die Ausnahmenummer;
  • springt dann zu einem gemeinsamen Handler
So

, wenn die gemeinsame Behandlungsroutine eintritt, wird der Stapel richtig ausgerichtet und enthält die Ausnahme / Interrupt-Nummer, Fehlercode (das nur ein Dummy sein kann), EFLAGS, CS und eip.

Meine Frage betrifft von den Interrupt-Handler zurück. Ich benutze iret zurückzukehren, nachdem die Ausnahmenummer und den Fehlercode aus dem Stapel herausnehmen, aber das funktioniert nicht für die Ausnahme nr 8; wenn ich den Fehlercode auf dem Stapel lassen, dann ist es wieder in Ordnung!

Fragen:

  • muss ich auf dem Stapel für Ausnahmen den Fehlercode verlassen, der den Fehlercode dort setzen? Wenn ja, wie iret zu bestimmen, ob es einen Fehlercode Pop hat oder nicht?
  • , sobald ich Unterbrechungen ermögliche ich immer Ausnahme 8 (Doppelfehler), aber dann in Ordnung, alles läuft (ich entwickle ein Hobby O). Ist das ein normales Verhalten oder muss ich einen Fehler irgendwo?
War es hilfreich?

Lösung

Wenn die CPU einen Fehlercode automatisch geschoben, der Handler muss Pop es vor dem iret. Die iret Anweisung nicht weiß, wo du herkommst, ob es ein Fehler ist, eine Falle oder eine externe Unterbrechung. Es tut immer das gleiche, und es wird davon ausgegangen, dass es keinen Fehlercode auf dem Stapel.

aus dem SDM Zitiert (Software Developer Manual), Band 3, Kapitel 5, Abschnitt 5.13 Titel Fehlercode:

  

Der Fehlercode wird auf den Stapel geschoben   als ein Doppelwort oder ein Wort (in Abhängigkeit von   die Standard-Interrupt, Trap oder Aufgabe   Torgröße). Um zu halten den Stapel ausgerichtet   die obere Hälfte für Doppelwort drückt,   des Fehlercodes ist reserviert. Hinweis   dass der Fehlercode nicht aufgetaucht, wenn   der IRET-Befehl ausgeführt wird, um   Rückkehr von einem Exception-Handler, so   der Handler muss den Fehlercode entfernen   bevor eine Rückkehr ausgeführt wird.

Hier finden Sie die IA-32 Software Developer Benutzerhandbuch hier : http://www.intel.com/products/processor/manuals/

Band 3 Teil 1, Kapitel 5, beschreibt Ausnahme und Interrupt-Handling. Volume 2 Teil 1 hat die Spezifikation für die iret Anweisung.

Andere Tipps

Ich schrieb ein kleines x86 O eine Weile zurück. Werfen Sie einen Blick auf die Datei isr. asm im cVS-Repository.

Beachten Sie, wie wir die Handler einrichten, die meisten einen Dummy-dword auf den Stapel schieben für die wenigen Handler zu berücksichtigen, die automatisch einen Fehlercode geschoben bekommen. Dann, wenn wir über eine iret zurückkehren können wir immer davon ausgehen, 2 D-Worte auf dem Stapel unabhängig von der Unterbrechung und führen esp ein Add, 8 vor dem iret Dinge aufzuräumen schön.

Das sollte Ihre erste Frage beantworten.

Was Ihre zweite Frage: Ein Doppelfehler, wenn Sie ermöglichen Interrupts, ... hmmm könnte ein Problem mit Paging, wenn Sie es nicht richtig eingerichtet haben. Könnte eine Million andere Sache zu:)

Ich hatte ein ähnliches Problem mit „Doppelfehler“, sobald ich Interrupts aktiviert. Nun, sie sah wie Doppelfehler, aber sie waren wirklich Timer-Interrupts!

Doppelfehler sind Interrupt-Nummer 8.

Leider ist ein Standard-PIC Konfigurationssignale Timer-Interrupts als Interrupt-Nummer (DEFAULT_PIC_BASE + TIMER_OFFSET) = (8 + 0) = 8.

All meine PIC Interrupts Ausblendung (bis ich bereit war, um richtig die PIC konfigurieren) zum Schweigen gebracht dieses Doppelfehler-Doppelgänger Timer-Interrupts.

(PICs die CPU benötigen Interrupts zu erkennen, bevor sie die nächste produzieren. Da der Code nicht die anfängliche Timer-Interrupt-Quittierung der PIC gab nie Sie mehr! Deshalb sollten Sie nur einen bekam, anstatt die zig ein man hätte erwarten können.)

  

Habe ich den Fehlercode auf dem Stapel für Ausnahmen verlassen haben, die den Fehlercode dort setzen?

Wie andere schon erwähnt, was Sie tun müssen entweder:

pop %eax
/* Do something with %eax */
iret

Oder wenn Sie den Fehlercode ignorieren:

add $4, %esp
iret

Wenn Sie dies nicht tun, iret wird der Fehlercode als das neue CS interpretieren, und Sie werden wahrscheinlich eine allgemeine Schutzverletzung zu erhalten, wie erwähnt unter: Warum von einer Seitenfehlerbehandler ist iret erzeugen 13 (allgemeine Schutzverletzung) und Fehlercode 0x18 unterbrechen?

Minimal Arbeiten Diese Seite Handler , dass ich angelegt habe, dies zu veranschaulichen. Versuchen Sie, die pop kommentieren und sehen es die Luft sprengen.

Vergleichen Sie die oben mit einem Divisionsfehler Ausnahme , die den Stapel nicht Pop.

Beachten Sie, dass, wenn Sie einfach int $14 tun, wird kein zusätzliches Byte geschoben. Dies geschieht nur auf der tatsächlichen Ausnahme

Intel Manual Volume 3 System Programming Guide - 325384-056US September 2015 Tabelle 6-1. „Protected-Mode Ausnahmen und Interrupts“ Spalte „Fehlercode“ enthält die Liste der Interrupts, die den Fehlercode oder nicht drücken.

38.9.2.2 "Page Fault Fehlercodes", erklärt, was der Fehler bedeutet.

Eine saubere Art und Weise damit zu umgehen ist eine Dummy-Fehlercode 0 auf dem Stapel für die Interrupts schieben, die dies nicht tun, um die Dinge einheitlich zu machen. James Molloy Tutorial tut genau das .

Der Linux-Kernel 4.2 scheint ähnlich, etwas zu tun. Unter arch / x86 / entry / entry64 .S es Modelle unterbricht mit has_error_code:

trace_idtentry page_fault do_page_fault has_error_code=1

und dann verwendet er auf der gleichen Datei wie:

.ifeq \has_error_code
pushq $-1 /* ORIG_RAX: no syscall to restart */
.endif

was tut die Push wenn has_error_code=0.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top