2016-05-22 4 views
-1

Ich habe die Kernel-Entwicklungstutorials im gesamten Internet durchgelesen, als ich die guten OS-Entwicklungstutorials fand.Wie funktioniert der auf dem Bildschirm angezeigte Code?

Ich ging durch den Code, aber ich konnte das nicht verstehen.

Der Code ist wie folgt:

int main(void){ 

char *str = "Hello, world", *ch; 

unsigned short *vidmem = (unsigned short*) 0xb8000; 
unsigned i; 

for (ch = str, i = 0; *ch; ch++, i++) 
    vidmem[i] = (unsigned char) *ch | 0x0700; 

for (;;); 
} 

Wenn ich den obigen Code mit Dev C++ kompiliert und erzeugen eine Win32-Konsole oder Windows-Anwendung abstürzt, wenn ich es laufen, und es sagt mir, dass mein Programm „hat hörte auf zu arbeiten "und endet. Es scheint in dieser Zeile in der Schleife zum Scheitern verurteilt:

vidmem[i] = (unsigned char) *ch | 0x0700; 

Was mit dem Code falsch ist, und wie kann ich das Problem lösen?

+0

* es zeigt Fehler in für Anweisung * ist keine Problembeschreibung. Es gibt * zwei * für Anweisungen - welche verursacht den Fehler? Und was genau ** Fehler zeigt es? Sie haben diese Informationen auf Ihrem Bildschirm direkt vor sich; Es gibt absolut keinen Grund für dich, es nicht in deine Frage aufzunehmen, also haben wir es auch. –

+0

Ich führe das Programm direkt auf Windows. Also wird es irgendein Problem geben, wie Zugriff auf illegalen Speicher (Speicherschutz) von 0xB8000. Werden Windows den Zugriff erlauben? –

+2

Nein, ein Windows-Programm unterstützt dies nicht. Win32-Anwendungen haben keinen direkten Zugriff auf den Videospeicher. Es wird wahrscheinlich dazu führen, dass das Programm fehlerhaft/abstürzt, wenn es das Update auf "vidmem" vornimmt. Ist Ihre eigentliche Frage - Warum stürzt mein Win32-Programm beim Ausführen ab? Dieser Code soll in einer Bare-Metal-Umgebung oder einer MS-DOS-Umgebung verwendet werden (würde es kompiliert mit TurboC oder Microsoft-C-Compiler, DOS und in einer DOS-Umgebung oder einem Emulator wie DosBox ausgeführt) –

Antwort

2

In der die for-Schleife:

for (ch = str, i = 0; *ch; ch++, i++) 
    vidmem[i] = (unsigned char) *ch | 0x0700; 

der Bedingungsabschnitt *ch instruiert den C Compiler Looping fortzusetzen, während die Ausdrücke wahr ist (nicht Null). Solange *ch kein NUL (\ 0) abschließendes Zeichen ist, wird der Ausdruck wahr sein und die Schleife fortsetzen. Wenn ein Zeichen erreicht wird, das Null ist, lautet der bedingte Ausdruck false und die Schleife wird beendet. Effektiv durchläuft es eine Zeichenkette, bis es das abschließende Zeichen NUL erreicht.

Der Grund für Ihren Absturz mit vidmem[i] = (unsigned char) *ch | 0x0700; ist, weil vidmem die Videospeicheradresse 0xb8000 gegeben wurde. Dieser Speicher ist für eine Win32-basierte Anwendung nicht zugänglich, und das Betriebssystem (Windows) führt zu Fehlern in der Anwendung und zeigt die Fehlermeldung über das Programm an, das nicht mehr funktioniert.

Der einzige Weg, dies zu lösen, ist es so kompilieren, dass es als ein MS-DOS-Programm verwendet werden kann:

  • Compile mit-16-Bit-C-Compiler und es in MS-DOS laufen oder ein MS-DOS-Emulator wie DOSBox
  • es in den Kernel kompilieren und es in einer Bare-Metal-Umgebung testen (QEMU, Virtualbox, VMWare usw.)

*ch | 0x0700 nimmt die aktuelle chara cter und bitweise OR auf 0x0700. Dies erzeugt effektiv ein 16-Bit-Wort mit dem Zeichen in den unteren 8 Bits und 0x07 in den oberen 8 Bits.

Dies wird durchgeführt, da jedes Zeichen, das in Standardfarbtext-Videomodi mit der Speicherregion 0xb8000 angezeigt wird, aus 2 Bytes besteht (ein 16-Bit-Wort). Dies wird in einer Wikipedia article beschrieben:

Video memory cell

Wenn das aktuelle Zeichen in der Schleife verarbeitet wird, ist der Buchstabe H (0x48), dann würde *ch | 0x0700 0x0748 werden, die dann an einer bestimmten Speicherstelle auf die gespeichert ist Videoanzeige.

Vielleicht möchten Sie über Bit-Manipulation in C lesen. Ich habe dieses tutorial gefunden, das helfen kann.

+0

Es gibt ein bitweises ODER, das das Zeichen und das Attribut trennt, warum? –

+0

@PantherCoder Ich habe meine Antwort ein wenig aktualisiert, um darauf zu tippen und einen Link zu einem Tutorial über die Bit-Manipulation in _C_ –

+0

Vidmem [0] zeigt an Adresse 0xB800. Wird es 8 Bits darin speichern oder 16 Bits speichern, da es geschützter Moduscode ist? –

Verwandte Themen