Frage

Ich bin in den Prozess der versucht, die ersten Bits eines Kernel zu hacken zusammen. Im Moment habe ich den gesamten Kernel als C-Code kompilierte nach unten, und ich habe es geschaffen, um es Text im Konsolenfenster angezeigt wird und all die feinen Güte. Nun möchte ich akzeptieren Tastatureingabe beginnen, damit ich tatsächlich einige Gebrauch der Sache machen und sich auf Prozess-Management geht.

Ich bin mit DJGPP zu kompilieren, und das Laden mit GRUB. Ich bin auch ein kleines bisschen Montag verwendet, die grundsätzlich direkt in meinen kompilierte C-Code springt und ich bin glücklich, von dort aus.

Die ganze Forschung, die ich getan habe, scheint bei $ 0x16 zu einem ISR-zu-Punkt in dem nächsten Zeichen aus dem Tastaturpuffer zu lesen. Von dem, was ich sagen kann, soll dies den ASCII-Wert in ah speichern und den Schlüsselcode in al, oder etwas in diesem Sinne. Ich versuche, dies mit der folgenden Routine in Inline-Assembler zu programmieren:

char getc(void) 
{
    int output = 0;

    //CRAZY VOODOO CODE
    asm("xor %%ah, %%ah\n\t"
        "int $0x16"
        : "=a" (output)
        : "a" (output)
        : 

        );

    return (char)output;
}

Wenn dieser Code aufgerufen wird, stürzt der Kern sofort. (Ich bin es auf VirtualBox läuft, habe ich nicht das Bedürfnis verspüren, etwas so Grund auf echter Hardware zu versuchen.)

Jetzt habe ich tatsächlich ein paar Fragen. Niemand konnte mir sagen, ob (da mein Code von GRUB gestartet wurde) Ich bin im Moment im Real-Modus oder im geschützten Modus läuft. Ich habe nicht den Sprung eine oder andere Weise gemacht, ich hatte vor, im Real-Modus läuft, bis ich ein Prozess Handler bekam einrichten.

So unter der Annahme, dass ich im Real-Modus laufen lasse, was ich tue, falsch, und wie kann ich es beheben? Ich brauche nur eine grundlegende getc Routine, vorzugsweise nicht-blockierend, aber ich werde gestopft werden, wenn Google auf diese überhaupt hilft. Sobald ich das tun kann, kann ich den Rest von dort aus.

Ich denke, was ich frage hier, ich bin irgendwo in der Nähe von dem richtigen Weg? Wie kommt man in der Regel geht über Tastatureingabe auf dieser Ebene zu bekommen?

EDIT: oohh ... so im geschützten Modus ich laufe. Dies ist sicherlich erklärt den Absturz versucht dann Real-Mode-Funktionen zugreifen zu können.

Also ich denke, ich bin auf der Suche nach, wie aus geschütztem Modus die Tastatur IO zuzugreifen. Ich könnte in der Lage sein, dass auf eigene Faust zu finden, aber wenn jemand zu wissen, geschieht frei fühlen. Nochmals vielen Dank.

War es hilfreich?

Lösung

Wenn Sie mit gcc kompilieren, wenn Sie die verrückt „.code16gcc“ verwenden Trick, um die Linux-Kernel verwendet (was ich sehr viel Zweifel), können Sie nicht im Real-Modus sein kann. Wenn Sie die GRUB Multi-Boot-Spezifikation verwenden, GRUB selbst ist für Sie in den geschützten Modus umgeschaltet wird. So, wie andere darauf hingewiesen, werden Sie direkt auf den 8042-kompatible Tastatur / Maus-Controller sprechen müssen. Es sei denn, es ist eine USB-Tastatur / Maus und 8042 Emulation deaktiviert ist, wo Sie sich einen USB-Stack benötigen (aber Sie können das „boot“ Protokoll für die Tastatur / Maus verwenden, die einfacher ist).

, sagte Niemand schreibt ein OS-Kernel war einfach.

Andere Tipps

Der Code du hast es versucht, einen Real-Mode-BIOS-Dienst zuzugreifen. Wenn Sie sich im geschützten Modus ausgeführt wird, was wahrscheinlich ist man bedenkt, dass Sie einen Kernel schreiben, dann wird die Unterbrechung nicht funktionieren. Sie werden eine der folgenden tun müssen:

  • Thunk die CPU in den real-Modus, so dass Sie sicher, dass die Interrupt-Vektortabelle korrekt ist, und verwenden Sie den Real-Mode-Code, den Sie haben oder
  • Schreiben Sie Ihren eigenen geschützten Modus-Tastatur-Handler (d verwenden, um die in / out Anweisungen).

Die erste Lösung wird eine Laufzeit-Performance-Overhead Whist der zweiten einzubeziehen einige Informationen über Tastatur IO benötigen.

Ich habe ein Stück GeekOS, die

zu tun scheint
In_Byte(KB_CMD);

und dann

In_Byte(KB_DATA);

einen Scancode zu holen. Ich habe es auf: keyboard.c und keyboard.h . KB_CMD und KB_DATA jeweils 0x64 und 0x60 sind. Ich könnte vielleicht auch darauf hinweisen, dass diese in einem Interrupt-Handler für intr erfolgt. 1

Sie sind das Richtige zu tun, aber ich glaube, dass djgpp erinnern nur geschützten Modus Ausgabe erzeugt, die Sie nicht Interrupts von aufrufen können. Können Sie Real-Modus fallen wie andere vorgeschlagen haben, oder würden Sie es vorziehen, die Hardware direkt ansprechen?

Für die Zwecke der Erklärung, nehmen wir an, Sie schrieben alles in Assembler-Sprache selbst, Bootloader und Kernel (* hust * Ich habe dies getan).

Im realen Modus können Sie die Verwendung der Interrupt-Routinen, die vom BIOS kommen. Sie können auch die Interrupt-Vektoren mit Ihren eigenen ersetzen. Jedoch sind alle Code ist 16-Bit-Code, der ist nicht binärkompatibel mit 32-Bit-Code.

Wenn Sie durch ein paar brennenden Reifen springen in dem geschützten Modus zu erhalten (einschließlich Neuprogrammierung der Interrupt-Controller, zu erhalten um die Tatsache, dass IBM verwendet Intel-reservierte Interrupts im PC), haben Sie die Möglichkeit zur Einrichtung 16- und 32-Bit-Code-Segmente. Dies kann dazu verwendet werden, um 16-Bit-Code auszuführen. So können Sie diese verwenden, um die getchar unterbrechen zugreifen!

... nicht ganz. Damit dies funktioniert, unterbricht, müssen Sie tatsächlich Daten in einem Tastaturpuffer, die von einem anderen ISR da lagen - die eine, die von der Tastatur ausgelöst wird, wenn eine Taste gedrückt wird. Es gibt verschiedene Probleme, die so ziemlich verhindern Sie das BIOS-ISR mit als tatsächliche Hardware-ISRs im geschützten Modus. So sind die BIOS-Tastatur-Routinen nutzlos.

BIOS-Videoanrufe, auf der anderen Seite, sind in Ordnung, weil es keine Hardware-Komponente ausgelöst ist. Sie haben ein 16-Bit-Code-Segment herzustellen, aber wenn die unter Kontrolle ist, dann können Sie Video-Modi und so etwas wechseln, indem Sie BIOS-Interrupts verwenden.

Zurück zur Tastatur: was Sie brauchen (wiederum unter der Annahme, dass Sie alle Code schreiben) ist ein Tastaturtreiber zu schreiben. Sofern Sie ein Masochist sind (ich bin einer) dann nicht dorthin gehen.

Ein Vorschlag: versuchen, ein Multitasking-Kernel in Echt Modus zu schreiben. (Das ist 16-Bit-Modus.) Sie können alle Interrupts BIOS verwenden! Sie haben keinen Speicherschutz erhalten, aber man kann immer noch präemptive Multitasking erhalten, indem das Timer-Interrupt Einhaken.

Nur eine Idee: Blick auf GRUB for DOS Quelle (asm.s), die console_checkkey Funktion wird mit dem BIOS-INT 16H Function 01, und nicht 00 funktionieren, wie Sie zu tun versuchen. Vielleicht würden Sie wollen überprüfen, ob eine Tasteneingabe zu warten.

Der console_checkkey Code setzt die CPU in dem real-Modus, um das BIOS zu verwenden, wie @ Skizz vorgeschlagen .

Sie können auch GRUB Funktionen versuchen, direkt mit (wenn auch noch im Real-Modus abgebildet).

Ein Hinweis auf das Lesen Montage Quelle: in dieser Version

movb    $0x1, %ah

Mittel bewegen konstante Byte (0x1) %ah registrieren

Die console_checkkey von GRUB asm.s:

/*
 * int console_checkkey (void)
 *  if there is a character pending, return it; otherwise return -1
 * BIOS call "INT 16H Function 01H" to check whether a character is pending
 *  Call with   %ah = 0x1
 *  Return:
 *      If key waiting to be input:
 *          %ah = keyboard scan code
 *          %al = ASCII character
 *          Zero flag = clear
 *      else
 *          Zero flag = set
 */
 ENTRY(console_checkkey)
  push  %ebp
  xorl  %edx, %edx

  call  EXT_C(prot_to_real) /* enter real mode */

  .code16

  sti       /* checkkey needs interrupt on */

  movb  $0x1, %ah
  int   $0x16

  DATA32    jz  notpending

  movw  %ax, %dx
  //call    translate_keycode
  call  remap_ascii_char
  DATA32    jmp pending

notpending:
  movl  $0xFFFFFFFF, %edx

pending:
  DATA32    call    EXT_C(real_to_prot)
  .code32

  mov   %edx, %eax

  pop   %ebp
  ret

Beispiel für die Abfrage der Tastatursteuerung:

Start:
      cli
      mov al,2        ; dissable IRQ 1
      out 21h,al
      sti

;--------------------------------------
; Main-Routine
AGAIN:
      in al,64h       ; get the status
      test al,1       ; check output buffer
      jz short NOKEY
      test al,20h     ; check if it is a PS2Mouse-byte
      jnz short NOKEY
      in al,60h       ; get the key

; insert your code here (maybe for converting into ASCII...)

NOKEY:
      jmp AGAIN
;--------------------------------------
; At the end
      cli
      xor al,al       ; enable IRQ 1
      out 21h,al
      sti
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top