Autor Thema: Syscall wird nicht aufgerufen  (Gelesen 18349 mal)

Savatage

  • Beiträge: 28
    • Profil anzeigen
Gespeichert
« am: 12. September 2016, 10:03 »
Hallo Team,

ich schaffe es einfach nicht einen Syscall von einem externen Programm auszulösen.
Die Initialisierung über Interrupt 48 sollte vollständig sein. In meinem Interrupt Handler fange ich den Syscall ab und leite ihn an die eigentliche Syscall Funktion weiter. Ich habe zunächst einen Syscall von einem externen Programm ausgelöst, und weil das nicht geklappt hat versuche ich nun von meiner init-Funktion des Kernels, nach der Initialisierung einen Syscall auszulösen:

asm("int $0x30" : : "a" (0), "b" ('0' + 1));
Das sollte ja einfach nur eine 1 ausgeben.
Zum Test habe ich mir im Interrupt-Handler mal ausgegeben welche Interrupts ausgelöst werden. Interrupt 0x30 ist jedoch nicht dabei. Es wird nur ständig der PIT (0x20) ausgelöst.

Kann es sein, dass der PIT sooft ausgelöst wird, das mein Syscall gar keine Chance hat an die Reihe zukommen? Ich habe dafür testweise den Syscall-Aufruf in der init-Funktion in eine Whileschleife gepackt um ihn immer wieder auszulösen. Allerdings wird der Syscall immer noch nicht ausgeführt.
Ich schaue jetzt noch mal die ganze Interrupt Initialisierung durch, weil doch eigentlich nur dort der Fehler sein kann, oder?

Gruß
Sava

kevin

  • Administrator
  • Beiträge: 2 767
    • Profil anzeigen
Gespeichert
« Antwort #1 am: 12. September 2016, 12:12 »
Also wenn die int-Instruktion ausgeführt wird, passiert auf jeden Fall etwas. Falls dein IDT-Eintrag für Interrupt 0x30 nicht gültig wäre, würdest du zumindest einen GPF bekommen (oder wenn auch das nicht klappt, Double Fault oder Triple Fault). Wenn du gar kein Anzeichen für irgendeinen Interrupt oder eine Exception siehst, dann würde ich behaupten, dass der Code gar nicht erst ausgeführt wird.

Zwischen zwei PIT-Interrupts müsste normal genug Zeit sein, um ordentlich Code ausführen zu können. Wenn du allerdings die ganze Zeit im Interrupthandler bleibst, könnte es natürlich passieren, dass der unterbrochene Code nie fortgesetzt wird. Halte ich für unwahrscheinlich.

Schau dir mal die Binärdatei an, ob der Compiler deine asm-Zeile nicht vielleicht sogar einfach weg"optimiert" hat. Wenn das das Problem ist, könnte ein asm volatile helfen.

Ansonsten qemu -d int und genau anschauen, welche Funktionen jeweils vom PIT-Interrupt unterbrochen werden und ob das die Stellen sind, von denen du erwartest, dass sie gerade laufen.
Thou shalt not follow the NULL pointer, for chaos and madness await thee at its end.

Savatage

  • Beiträge: 28
    • Profil anzeigen
Gespeichert
« Antwort #2 am: 12. September 2016, 18:38 »
Wie immer danke für die schnelle Antwort.

Zitat
Wenn du gar kein Anzeichen für irgendeinen Interrupt oder eine Exception siehst, dann würde ich behaupten, dass der Code gar nicht erst ausgeführt wird.
Das bestätigt mich immerhin das meine Interruptabhandlung funktioniert und ich da nicht weiter suchen brauche.

Zitat
Wenn du allerdings die ganze Zeit im Interrupthandler bleibst, könnte es natürlich passieren, dass der unterbrochene Code nie fortgesetzt wird. Halte ich für unwahrscheinlich.
Dies halte ich auch für unwahrscheinlich, weil meine Tastatureingaben reagieren und der entsprechende Interrupt für einen Tastenanschlag ausgeführt wird.

Zitat
Wenn das das Problem ist, könnte ein asm volatile helfen.
Ein asm volatile ändert leider gar nichts. Das wäre natürlich schön einfach gewesen :)

Zitat
Ansonsten qemu -d int und genau anschauen, welche Funktionen jeweils vom PIT-Interrupt unterbrochen werden und ob das die Stellen sind, von denen du erwartest, dass sie gerade laufen.
qemu -d int zeigt mir die Kernel Register und gefühlt 1000 andere Dinge? Das habe ich noch nie benutzt und muss mich da erst mal durch kämpfen. Wenn ich diesbezüglich weitere Infos habe, melde ich mich wieder. Bis dahin bin ich über weitere Tipps dankbar.

Gruß
Sava

kevin

  • Administrator
  • Beiträge: 2 767
    • Profil anzeigen
Gespeichert
« Antwort #3 am: 12. September 2016, 19:27 »
qemu -d int zeigt mir die Kernel Register und gefühlt 1000 andere Dinge?
Es zeigt dir für den jeden Interrupt die Details zu diesem Interrupt an (also Vektor, Error Code, usw.) und zusätzlich einen CPU-Dump. Aus dem CPU-Dump interessiert dich im Moment wahrscheinlich eip, also die Adresse, an der gerade Code ausgeführt wurde als der Interrupt ausgelöst wurde.
Thou shalt not follow the NULL pointer, for chaos and madness await thee at its end.

Savatage

  • Beiträge: 28
    • Profil anzeigen
Gespeichert
« Antwort #4 am: 16. September 2016, 09:12 »
Problem gelöst.
Die For-Schleife war nicht richtig, sodass der Code nicht ausgeführt wurde.
Allerdings bin ich mit der Ausgabe noch nicht so recht zufrieden. Das ist die Schleife:
int i;
for (i = 0; i < 5; i++) {
asm("int $0x30" : : "a" (0), "b" ('0' + i));
}

Also erwarte ich als Ausgabe: 01234
Die tatsächliche Ausgabe ist aber:
t
0t
1t
2t
3t
4t

Nach jedem Syscall kommt irgendwo hier noch ein t und ein \n.
Es scheint wohl dass mein Konsolentreiber noch nicht ganz rund läuft. Da schau ich jetzt noch mal drüber.

Danke bisher erstmal.

Savatage

  • Beiträge: 28
    • Profil anzeigen
Gespeichert
« Antwort #5 am: 20. September 2016, 08:41 »
ich kriege das Problem mit dem zusätzlichen t in der Ausgabe nicht gelöst. Das Register ebx ist korrekt gefüllt und ist doch eigentlich nichts anderes als ein Hex-wert.

kevin

  • Administrator
  • Beiträge: 2 767
    • Profil anzeigen
Gespeichert
« Antwort #6 am: 20. September 2016, 10:46 »
Also der gepostete Code befüllt nicht ebx, sondern nur bl, falls das für deinen Kernel irgendeinen Unterschied machen sollte.

Hast du ebx denn mal als Hexzahl im Kernel ausgeben lassen?
Thou shalt not follow the NULL pointer, for chaos and madness await thee at its end.

Savatage

  • Beiträge: 28
    • Profil anzeigen
Gespeichert
« Antwort #7 am: 21. September 2016, 08:51 »
ich habe mittels qemu -d int geschaut was jeweils zum Syscall Aufruf in ebx drin steht.
ich dachte der erste Parameter im asm Befehl wird in eax geschrieben ( die 0 ) und der zweite in ebx?
Was genau meinst du mit bl?

Ich  glaube so langsam fällt es auf, dass ich nicht 100% verstanden habe wie der asm Befehl funktioniert. Ich werde mich mal schlau machen und hoffe dabei auf die Lösung zu stoßen. 

OsDevNewbie

  • Beiträge: 282
    • Profil anzeigen
    • YourOS Kernel
Gespeichert
« Antwort #8 am: 21. September 2016, 09:18 »
bl ist das erste Byte im ebx-Register. Es wird nur dieses befüllt, weil '0' nur 1 Byte entspricht und somit '0'+x auch nur ein Byte belegt. Daher wäre es nicht falsch anzunehmen, dass der Compiler nur das bl-Register beschreibt. Durch das beschreiben, des bl-Registers wird der Inhalt des restlichen Register aber nicht gelöscht und deshalb kann dort noch "Abfall" enthalten sein.
Viele Grüsse
OsDevNewbie

Ein Computer ohne Betriebsystem ist nicht mehr wert als ein Haufen Schrott.
Ein Computer ist eine Maschine, die einem Lebewesen das kostbarste klaut, was sie selber nicht hat:
DIE ZEIT DES LEBENS

Savatage

  • Beiträge: 28
    • Profil anzeigen
Gespeichert
« Antwort #9 am: 21. September 2016, 09:39 »
ah, ok! Vielen Dank.
Wenn ich
asm("int $0x30" : : "a" (0), "b" ('0' + 3));ausführe steht in ebx: 00000033
Führe ich hingegen
asm("int $0x30" : : "a" (0), "b" (3));aus steht in ebx: 00000003

Also steht im 2. Byte von ebx immer noch eine 3 - sozusagen als Abfall.

Meine Ausgabe (kprintf("%c", cpu->ebx)) im ersten Fall ist:
t
3t
3t
...
oder (kprintf("%d", cpu->ebx)):
t
51t
51t
...


im Zweiten Fall
t
 t
 t
...


Die 51 passt ja schon mal weil 33h = 51d. Trotzdem verstehe ich nicht wo das t herkommt.


Savatage

  • Beiträge: 28
    • Profil anzeigen
Gespeichert
« Antwort #10 am: 21. September 2016, 09:46 »
ich Esel... Einfach ignorieren... hatte tatsächlich noch zum debuggen ein t\n ausgegeben. Kaum nimmt man es raus, schon funktionierts.

trotzdem sehr hilfreich sich dem asm Befehl mal genau anzusehen.

kevin

  • Administrator
  • Beiträge: 2 767
    • Profil anzeigen
Gespeichert
« Antwort #11 am: 21. September 2016, 10:29 »
Also steht im 2. Byte von ebx immer noch eine 3 - sozusagen als Abfall.
Nicht ganz. ;)

Ein Byte hat 8 Bit, also zwei Hexziffern, nicht nur eine. 0x33 ist der Inhalt des ersten Bytes. Und das ist der ASCII-Code für das Zeichen '3', also passt genau.
Thou shalt not follow the NULL pointer, for chaos and madness await thee at its end.

 

Einloggen