Hypercell ein ] Hypercell aus ] Zeige Navigation ] Verstecke Navigation ]
c++.net  
   

Die mobilen Seiten von c++.net:
https://m.c-plusplus.net

  
C++ Forum :: Projekt: OS-Development  ::  Division durch Null     Zeige alle Beiträge auf einer Seite Auf Beitrag antworten
Autor Nachricht
w_ciossek
Mitglied

Benutzerprofil
Anmeldungsdatum: 12.09.2011
Beiträge: 18
Beitrag w_ciossek Mitglied 17:50:58 10.01.2018   Titel:   Division durch Null            Zitieren

Ich habe inzwischen die IDT eingerichtet, als auch die isr- und irq-Routinen, die ihrerseits einen Handler aus einen array aufrufen, bzw. entsprechend bei den ISR-Routinen eine Fehlermeldung ausgeben. Der ISR-Handler als auch der IRQ-Handler werden immer mit einen EOI beendet. Der PIT wurde so programmiert,
daß die Interrupts von 0 bis 15 auf die IRQ nummern 32 bis 47 verschoben wurden.
die ISR-Routinen 0 bis 31 decken sich mit den Interruptnummern von 0 bis 31.

Code:
// EOI
if (Interruptnr>=40)
  {
    outportb(0xA0,0x20);
  }
 
outportb(0x20,0x20);


Um die IRQ- und ISR- Routinen als auch deren Handler zu testen, baute ich
eine "Division durch Null" ein.

Wenn ich im C++ Programm Anweisungen wie
Code:
unsigned char x=1;
x=x/0;

ausführe, passiert nichts! Offenbar fängt der Compiler diese Ausnahme ab, auch wenn der gcc-Compiler nur eine Warnung ausgibt.

Wenn ich jedoch Assembleranweisungen wie
Code:
asm("mov $0x1, %ax;"
    "mov $0x0, %bx;"
    "idiv %bx");

in den C++-Code einfüge, dann entsteht eine "Division durch Null"-Ausnahme. Jedoch wird sie endlos generiert, so als würden die EOI-Anweisungen ignoriert werden.
Ich befürchte, daß bei allen 32 ISR-Routinen dieses passieren würde, wenn von der Prozessorseite die Interruptnummern von 0 bis 31 erzeugt werden.

Wie kann man den int 0 wieder abstellen?
Mr X
Mitglied

Benutzerprofil
Anmeldungsdatum: 18.09.2007
Beiträge: 1729
Beitrag Mr X Mitglied 21:26:47 10.01.2018   Titel:              Zitieren

Zitat:
Offenbar fängt der Compiler diese Ausnahme ab, auch wenn der gcc-Compiler nur eine Warnung ausgibt.

Kann ich in PrettyOS mit unserem GCC-Crosscompiler nicht reproduzieren. Hier stürzt es ordnungsgemäß ab mit der Division durch 0.

Zitat:
Jedoch wird sie endlos generiert, so als würden die EOI-Anweisungen ignoriert werden.

Grundsätzlich sollte das nicht passieren. Was machst du denn als "EOI"? Dem PIC brauchst du kein EOI signalisieren bei Exceptions, du musst ein iret im Interrupthandler machen.
w_ciossek
Mitglied

Benutzerprofil
Anmeldungsdatum: 12.09.2011
Beiträge: 18
Beitrag w_ciossek Mitglied 11:56:33 11.01.2018   Titel:              Zitieren

Bei Hardwareinterrupts wie beispielsweise beim Druck auf eine Tastaturtaste wird die Interruptleitung des Prozessors zurückgesetzt, so daß es keine unendlichen Wiederholungen gibt. Jetzt weiß ich noch nicht, ob bei einer Aussnahme ebenfalls die Interruptleitung gesetzt wird. Vielleicht gibt es ein Statusflag, welches das Auftauchen eines Traps anzeigen.

Bei mir werden alle Interrupts und Traps mit einen iret beendet.
Soweit ich weiß, werden bei iret im Gegensatz zu ret nur mehr Register vom Stack heruntergeholt und sti intern ausgeführt. Ob es ebenfalls die Interruptleitung in jedem Falle zurücksetzt, weiß ich nicht.
Assembler:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
extern _IRQ_Handler
extern _ISR_Handler
_isr0:                  ; 0 Division durch Null Ausnahme
      cli
      push dword 0      ;Fehlernummer
      push dword 0      ;Interruptnr
      jmp ISR_Routine
.
.
.
_irq0:          ;
      cli
      push dword 0
      push dword 0
      jmp IRQ_Routine
.
.
.
ISR_Routine:
      push eax
      push ebx
      push ecx
      push edx
      push ebp
      push esi
      push edi
      push ds
      push es
      push fs
      push gs
 
      mov ax, 0x10
      mov ds, ax
      mov es, ax
      mov fs, ax
      mov gs, ax
 
      push esp      ; Parameter
      call _ISR_Handler
      pop esp
   
      pop gs
      pop fs
      pop es
      pop ds
      pop edi
      pop esi
      pop ebp
      pop edx
      pop ecx
      pop ebx
      pop eax
 
      add esp, 8 ; Fehlernr und Interruptnr vom Stack loeschen
      iret
IRQ_Routine:
      push eax
      push ebx
      push ecx
      push edx
      push ebp
      push esi
      push edi
      push ds
      push es
      push fs
      push gs
 
      mov ax, 0x10
      mov ds, ax
      mov es, ax
      mov fs, ax
      mov gs, ax
 
      push esp      ; Parameter
      call _IRQ_Handler
      pop esp
   
      pop gs
      pop fs
      pop es
      pop ds
      pop edi
      pop esi
      pop ebp
      pop edx
      pop ecx
      pop ebx
      pop eax
 
      add esp, 8
      iret


und im C-Code sieht das dann so aus:
C++:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
void IRQ_Handler(uint32 esp)
{
  CRegister *r;
 
  r=(CRegister *)esp;
 
  void (*handler)(CRegister* r);
 
  handler = (void (*)(CRegister *)) IRQ_Routinen[r->Interruptnr];
 
  if (handler)
    {
      k_printf("Interruptnr=%d\n",r->Interruptnr);
      handler(r);
    }
 
  if (r->Interruptnr+32>=40)
    {
      outportb(0xA0,0x20);
    }
 
  outportb(0x20, 0x20);
}
 
void ISR_Handler(uint32 esp)
{
  uint8 Farbe = k_getcolor();
  uint8 NFarbe = Farbe;
 
  CRegister *r;
 
  r=(CRegister *)esp;
   
  if (r->Interruptnr<32)
    {
      NFarbe = NFarbe & 0xF0;
      NFarbe = NFarbe | 0x04;
      k_setcolor(NFarbe);
      k_printf("%s",Fehlermeldungen[r->Fehlernr]);
      k_setcolor(Farbe);
      k_printf("\n");
    }
  else
  if (r->Interruptnr>0 && r->Interruptnr<MaxRoutinen)
    {
      k_printf("Interruptnr=%d",r->Interruptnr);
      k_setcolor(Farbe);
      k_printf("\n");
    }
 
  if (r->Interruptnr>=40)
    {
      outportb(0xA0,0x20);
    }
 
  outportb(0x20,0x20);
}


ich mußte, um die Struktur CRegister zu füllen, diese vielen push-Anweisungen machen. Vor dem Aufruf der Handler auch ein push esp, da ich sonst den Handler
als Handler(CRegister *r) keinen Zugriff auf die gepushten Werte in r hatte, da der C-Compiler beim Aufruf des Handlers die Parameter bei Strukturen oder Klassen nicht direkt vom Stack gelesen werden können. Aus diesen Gründen habe ich einfach eine Adresse des Stacks als Parameter übergeben. Der Aufruf erfolgt dann immer korrekt und ich kann auf die gepushten Register über die Struktur CRegister zugreifen.


Interessant jedoch ist bei mir das Verhalten des gcc-Compilers
C++:
  volatile int a=1;
  volatile int b=0;
  volatile int x=0;
 
  x=a/b;


Bei diesen Code erreiche ich eine Ausnahme. Lasse ich das volatile weg, passiert nichts! Das ist nicht sehr gut!
Schreibe ich jedoch unter Linux eine solche Sequenz, dann meldet er in jedem Falle (mit volatile oder ohne) etwas, und zwar einen Gleitkommafehler!

Ich habe Beim Eintrag der ISR-Routinen in die IDT-Tabelle beim Flag von Bits 0 bis 3, wo der Typ festgelegt ist, das 80386 Interrupt Gate 0b1110 gesetzt.
In der Annahme, daß die ISR-Routinen eigentlich Traps und keine Interrupts sind,
habe ich nun 0b1111 für 80386 Trap Gate gesetzt.

Doch auch hier wird Trap 0 unendlich wiederholt aufgerufen. Bei den IRQ's läuft alles normal


Zuletzt bearbeitet von w_ciossek am 14:54:40 11.01.2018, insgesamt 5-mal bearbeitet
Mr X
Mitglied

Benutzerprofil
Anmeldungsdatum: 18.09.2007
Beiträge: 1729
Beitrag Mr X Mitglied 17:52:05 11.01.2018   Titel:              Zitieren

Zitat:
Bei diesen Code erreiche ich eine Ausnahme. Lasse ich das volatile weg, passiert nichts! Das ist nicht sehr gut!
Schreibe ich jedoch unter Linux eine solche Sequenz, dann meldet er in jedem Falle (mit volatile oder ohne) etwas, und zwar einen Gleitkommafehler!

Möglicherweise macht GCC, wenn aktiviert, da írgendwie SSE draus.

Zitat:
Soweit ich weiß, werden bei iret im Gegensatz zu ret nur mehr Register vom Stack heruntergeholt und sti intern ausgeführt. Ob es ebenfalls die Interruptleitung in jedem Falle zurücksetzt, weiß ich nicht.

Bei einem Softwareinterrupt sollte die Interruptleitung des Prozessors nicht betroffen sein. Bin mir aber nicht völlig sicher; habe meine Unterlagen nicht zur Hand.
Das outportb(0x20,0x20); kannst du dir bei ISRs definitiv sparen. Der PIC hat mit ISRs nichts zu schaffen.

Zitat:

Ich habe Beim Eintrag der ISR-Routinen in die IDT-Tabelle beim Flag von Bits 0 bis 3, wo der Typ festgelegt ist, das 80386 Interrupt Gate 0b1110 gesetzt.
In der Annahme, daß die ISR-Routinen eigentlich Traps und keine Interrupts sind,
habe ich nun 0b1111 für 80386 Trap Gate gesetzt.

Die IDT von PrettyOS enthält keine Trap-Gates, soweit ich sehe.


Zu deinem eigentlichen Problem habe ich folgende Vermutung: Bei einer Exception zeigt EIP weiterhin auf die Instruktion, die den Fehler verursacht hat. Das ist auch durchaus sinnvoll, wenn z.B. geswappte Pages dann im Handler nachgeladen werden, und danach dann der Code erfolgreich ausgeführt werden kann. Ähnliches gibts im Zusammenhang mit der FPU. Im konkreten Fall heißt es aber: Es wird wieder die Division durch 0 ausgeführt. D.h., du müsstest wohl den schuldigen Prozess beenden, oder manuell über den Befehl hinweg springen.
w_ciossek
Mitglied

Benutzerprofil
Anmeldungsdatum: 12.09.2011
Beiträge: 18
Beitrag w_ciossek Mitglied 21:40:09 11.01.2018   Titel:              Zitieren

Ich bin mit der Programmierung noch nicht so weit, daß ich schon USER-Prozesse erzeugen kann, und es macht offenbar kein Sinn, im Kernel-Mode Traps auszulösen. Das letztere scheint wohl zu sein, daß der EIP wohl noch auf dieser Instruktion steht. Gewöhnlicherweise werden USER-Prozesse bei einer Ausnahme beendet.
C++ Forum :: Projekt: OS-Development  ::  Division durch Null   Auf Beitrag antworten

Zeige alle Beiträge auf einer Seite




Nächstes Thema anzeigen
Vorheriges Thema anzeigen
Sie können Beiträge in dieses Forum schreiben.
Sie können auf Beiträge in diesem Forum antworten.
Sie können Ihre Beiträge in diesem Forum nicht bearbeiten.
Sie können Ihre Beiträge in diesem Forum nicht löschen.
Sie können an Umfragen in diesem Forum nicht mitmachen.

Powered by phpBB © 2001, 2002 phpBB Group :: FI Theme

c++.net ist Teilnehmer des Partnerprogramms von Amazon Europe S.à.r.l. und Partner des Werbeprogramms, das zur Bereitstellung eines Mediums für Websites konzipiert wurde, mittels dessen durch die Platzierung von Werbeanzeigen und Links zu amazon.de Werbekostenerstattung verdient werden kann.

Die Vervielfältigung der auf den Seiten www.c-plusplus.de, www.c-plusplus.info und www.c-plusplus.net enthaltenen Informationen ohne eine schriftliche Genehmigung des Seitenbetreibers ist untersagt (vgl. §4 Urheberrechtsgesetz). Die Nutzung und Änderung der vorgestellten Strukturen und Verfahren in privaten und kommerziellen Softwareanwendungen ist ausdrücklich erlaubt, soweit keine Rechte Dritter verletzt werden. Der Seitenbetreiber übernimmt keine Gewähr für die Funktion einzelner Beiträge oder Programmfragmente, insbesondere übernimmt er keine Haftung für eventuelle aus dem Gebrauch entstehenden Folgeschäden.