Eigenes OS?
-
Also wenn schon, denn schon:
Hinweis: Die Verwendung des High und Low Byte eines Registers in Verbindung mit dem Befehl mov, wenn genau so gut das gesamte 16-Bit-Register mit einem Befehl bedient werden könnte, ist eine Verschwendung von Speicherplatz und Prozessortakten (in diesem Fall 1 Byte und max. z.B. auf einem 486 1 Takt zusätzlich)! Dies geschieht in obigem Fall nur der besseren Übersicht wegen. Performanter Programmierstil ist dies nicht.
Also anstelle
mov al,10 (mov al, 0x0A)
mov ah, 2verwendet man performant
mov ax, 0x020A
Erhard Henkes schrieb:
Nun wollte ich schreiben, wieviele Takte man oben und unten benötigt, habe aber keine Übersichtslisten gefunden. Kennt sich da jemand aus? Link?
Ist alles ziemlich undurchsichtig. Quellen waeren Docs aktueller CPU von den Herstellern. Wie aber bereits erwaehnt, braucht schon der 486 max. 1 Takt fuer so ein mov - auf neueren CPU werden das vermutlich nicht mehr sein.
Zumindest AMDs fruehere 64Bitter liessen sich von sowas AFAIR auch gern mal die Pipeline durcheinander bringen, also wahrscheinlich dann auch 2 Takte.
-
Also wenn schon, denn schon:
Was meinst Du damit?
-
Ich habe mir erlaubt, deinen Text hauptsaechlich um die Erwaehnung des zusaetzlichen Speicherplatzverbrauchs zu erweitern (was in einem BL wichtiger sein duerfte als 1 verpulverter CPU-Takt), falls das nicht aufgefallen sein sollte...
-
Bezüglich Takte gibt es hier http://www.agner.org/optimize/ unter "4. Instruction tables: Lists of instruction latencies, throughputs and micro-operation breakdowns for Intel and AMD CPU's" eine schöne Übersicht über die ganzen Befehle und deren Takte, uOps und was weiss der Teufel noch was... falls es jemand genauer wissen möchte.
-
Ich habe mir erlaubt, deinen Text hauptsaechlich um die Erwaehnung des zusaetzlichen Speicherplatzverbrauchs zu erweitern (was in einem BL wichtiger sein duerfte als 1 verpulverter CPU-Takt), falls das nicht aufgefallen sein sollte...
Sorry! Danke für die Ergänzung. Jedes Byte im ersten Sektor ist wertvoll.
-
Ich wollte mal auf die Schnelle in den PM umschalten, macht aber einen Reset. Ich finde momentan den Fehler einfach nicht. Liegt es an GDTR/GDT, am fehlenden IDT oder am far jump?
Vielleicht sollte ich doch auf C umsatteln? Mir gefällt Assembler aber didaktisch besser, weil es klarer ist. Kann bitte jemand nachhelfen?
..
-
Ich wuerde spontan auf deine GDT, bzw. GDTR tippen. Bist du dir zB. sicher, dass die Basisadresse im GDTR auch stimmt?
-
Nein, ich habe da zu viel aus verschiedenen Ecken zusammen geflickt. Das funktioniert leider auch nicht, denke aber, dass es so richtig ist:
gdtr: dw gdt_end - gdt - 1 ; lenght of GDT dd gdt gdt: dw 0 ; (0h) Null Segment dw 0 db 0 db 0 db 0 db 0 code_gdt equ $-gdt dw 0x0FFFF dw 0x0000 db 0x00 db 0x9A db 0xCF db 0x00 data_gdt equ $-gdt dw 0x0FFFF dw 0x0000 db 0x00 db 0x92 db 0xCF db 0x00 video_gdt equ $-gdt dw 3999 ; Limit 80*25*2-1 dw 0x8000 db 0x0B ; Base 0xB8000 db 0x92 db 0x00 db 0x00 gdt_end:
Die Basis-Adresse ist doch das Label gdt?
-
Habe gerade mal bei uns im Forum recherchiert:
http://www.c-plusplus.net/forum/viewtopic-var-t-is-219332.html
Da klagt auch jemand über Neustart. Da lag es am far jump.
Naja, aus Fehler kann man ja auch lernen. Da scheitern die meisten.Wenn ich org 0x10000 vorne rein setze, funktionieren die normalen Befehle im Real Mode. Bei PM stürzt er aber sofort ab.
Wenn ich org 0x7c00 vorne rein setze, funktionieren die normalen Befehle im Real Mode natürlich nicht mehr. Bei PM stürzt er aber nicht mehr ab, aber er zeigt auch nichts an (z.B. 'A'). Man kann dann noch Zeichen eingeben, Puffer von 31 Zeichen läuft noch.
org 0x10000 ist richtig. Wie muss ich den far jump schreiben?
Was ist hier der richtige Selektor für den Jump?
db 0xea ;instruction for FAR JUMP dw do_pm ;Offset for jump dw 0x8 ;selector of the segment for the jump ; jmp code_gdt:do_pm does not work?!
-
Tja, das ist eben so eine Sache mit den Labels in Asm. Praktisch sind das ja beim x86 eigentlich immer offsets. Da muss auch jeweils die Basis-Adresse zu stimmen (wird auch beim nasm mittels org festgelegt).
Kurze Ueberlegung:
Wenn du deinen Code nach 0x10000 laedst und die Segmentregister dann mit 0x1000 laedst, klappt das ohne, bzw. mit org 0 natuerlich erstmal im RM problemlos, da dein Code an Offset 0 des Segments direkt beginnt. Im GDTR muss dann aber die physikalische mit absoluter Basis 0 stehen! Das selbe beim far jump zum PM - der offset-Teil muss dort dann relativ zur Basisadresse, die im angegebenen Code-Selector steht, passen.
Wenn du stattdessen einfach so die labels da rein schreibst, ohne zu beruecksichtigen, dass sich deren Adresse so ohne Weiteres nur auf das RM-Segment 0x1000 beziehen, geht die Sache schief.
-
<< Zwischenstand gelöscht >>
-
Sorry, ich bin gerade auch zu bematscht in der Birne, um konkreter zu werden. Da kann ich mich erst nach einer Muetze Schlaf konzentriert mit befassen...
-
Erhard Henkes schrieb:
Geht das nicht einfacher als unten im Code?
wahrscheinlich nicht.
Erhard Henkes schrieb:
Ist schwierig zu verstehen.
du wolltest doch unbedingt das x86-flickwerk nehmen. jetzt musst da wohl durch.
-
Das ist nicht unbedingt ein Problem von NASM (bzw. mir faellt kein Assembler ein, mit dem das wirklich geschickter ginge), sondern eine Eigenart des x86, dass hier in einem Code einfach verschiedene Adressierungsmechanismen zum Zugriff auf die selben Labels benutzt werden.
Am saubersten waere es IMHO, wenn du dafuer sorgst, dass dieses Phaenomen der unterschiedlichen Basisadressen gar nicht erst auftritt. Dazu musst du in diesem Code-Abschnitt immer die Segment-Basis 0 benutzen (im RM also alle Segmentregister auf 0 setzen, dh. der Code muss auch in den ersten 64K Speicher liegen, im PM die Basisadresse fuer Zugriffe auf diesen Code auch 0) und an den Anfang des Codes entsprechend eine org-Anweisung mit dem Start-Offset des Codes zur Basis 0 (also das Offset innerhalb der ersten 64k, wo der Code anfaengt).
32Bit-Segmente mit Basis 0 und bis zu 4GB Groesse zu verwenden, bietet sich dann im PM spaeter natuerlich so oder so auch an...
So kannst du dir dann auch zB. den extra-Descriptor fuer die Textausgabe sparen und hast einen leichteren Uebergang zu C-Code (wie wuerde man direkt aus c heraus ueberhaupt mit verschiedenen Selectoren umgehen?).
So solltest du keine Probleme mit irgendwelchen "org"ien oder "Kunstgriffen" mit addierten Basisadressen o.Ae. bekommen.Falls du deinen Code unbedingt im Segment 1000 lassen willst, kommst du um einiges Gebastel mit Addition der phys. Basisadresse (10000) zur Adresse der GDT und evtl. die Differenz der Basisadressen der Code-Segmente in RM und PM zum Far-Jump in den PM wahrscheinlich nicht umhin.
Das waere dann immerhin evtl. eine gute Gelegenheit, die Adressierungsmechanismen des RM, rein physikalischer Adressen und PM ohne paging genauer zu beleuchten... wenn du das wirklich sauber kommentierst und erklaerst.Noch zu etwas Anderem:
In meinem letzten OS-Projekt in der Uni, und nun in deinem Code, wurde mir mal wieder deutlich vor Augen gefuehrt, dass es nicht "cool", sondern hoechstens verwirrend ist, irgendwelche weitgehend unkommentierten Zahlen zur Darstellung von Bit-flags hinzuklatschen. Du tust deinen Lesern sicher einen Gefallen, wenn du flags in den Deskriptoren genauer kommentierst.Mich wuerde auch interessieren, weshalb du meinen Tipp zu deinem strcmp nicht uebernummen hast?
-
Mich wuerde auch interessieren, weshalb du meinen Tipp zu deinem strcmp nicht uebernummen hast?
@Nobuo T:
Sorry, hatte vergessen, es auch im Tutorial einzutippen. Dein Tipp ist hervorragend! Code ist jetzt kürzer: Carry-Flag weg und nur noch eine Rücksprungadresse '.done'..
Ich hoffe zumindest, dass ich Dich so richtig verstanden habe.
Wie hättest Du dies mit 'test op,op' (AND-Verknüpfung ohne Speicherung, nur Flags setzen) gemacht? Das nimmt man doch eher, um zu testen, ob ein bestimmtes Bit gesetzt ist? z.B. test AL, 64 (check auf Bit 6)Bezüglich RM -> PM bin ich noch am Grübeln. da muss ich noch einige Hobby-OS analysieren. Vielleicht kann man die besten Ideen aus allen heraus kristallisieren. Die Idee von Nobuo T ist auf jeden Fall bedenkenswert. Welchen offset würde man da mittels org wählen und warum? Mir ist noch nicht klar, warum die meisten den Kernel (oder ersten Teil des Kernels) nach 10000h setzen.
... dass es nicht "cool", sondern hoechstens verwirrend ist, irgendwelche weitgehend unkommentierten Zahlen zur Darstellung von Bit-flags hinzuklatschen. Du tust deinen Lesern sicher einen Gefallen, wenn du flags in den Deskriptoren genauer kommentierst.
Völlig richtig! So darf man das auch nicht machen, war nur Test.
Besser: binäre Darstellung im Assemblercode mit Kommentar, der die einzelnen Bits bezüglich ihrer Aufgabe beschreibt/erklärt.
-
Zunächst mal vielen Dank an alle, die mich bisher nicht entmutigten, sondern mich mit Rat und Tat unterstützen. IMHO ein wirklich konstruktives Subforum.
Für die Ungeduldigen:
Nun wollen wir mal versuchsweise von RM nach PM schalten (ist noch nicht im Tutorial, weil didaktisch noch nicht klar genug), indem man den Befehl "pm" eingibt.Ich habe zunächst die Methode der Kalkulation für die GDTR-Werte nach dem Umschalten verwendet, um zu sehen, ob das alles gut klappt. Funktioniert wirklich. Didaktisch ist dieser Weg nicht perfekt, lässt sich aber dennoch erklären. Vielleicht kann Nobuo T seine Idee daneben stellen zum Vergleich.
Nun fehlt didaktisch nur noch ein Command Line Interpreter und ein Befehl "RM" im Protected Mode, der den Rücksprung nach Real Mode gewährt.
In Zeile 277 steht noch nichts Sinnvolles als Zieladresse (zur Zeit wird der Code "gedumpt", ich habe mal in DL mit den Farben gespielt). Hat jemand eine kleine gute Idee für den Einstieg?
Typisch wäre jetzt ein Sprung in einen C-Kernel. Aber inzwischen gefällt mir Assembler viel besser. Man gewöhnt sich an alles.
-
Hallo,
habe mal den Code in bochs ausprobiert, weiss nicht, ist es normal, dass nach dem Kommando pm lauter farbiger Zeichen erscheinen...
Bezüglich der drei Zeilen:db 0xea ; instruction code for FAR JUMP dw ProtectedMode ; offset for jump dw 0x8 ; selector of the segment for the jump
Man kann sich die Binärdatei mit dem Programm ndisasm, das mit nasm mit dabei ist, disassemblieren lassen, z.B. so:
c:\nasm-2.06rc6\ndisasm.exe -b 16 kernel.bin
Dann sieht man, wie ndisasm es interpretiert:
000001E4 EA57020800 jmp word 0x8:0x257
Also kann man die oberen 3 Zeilen durch eine ersetzen:
jmp word 0x8:ProtectedMode
Damit wird scheinbar auch ein FAR JUMP generiert. Man kann es auch hier nachlesen: http://www.nasm.us/doc/nasmdo10.html#section-10.1
Ich hab es mal ausprobiert und es kommen immer noch die farbigen Zeichen - also wahrscheinlich funktioniert es wie vorher. Und die ndisasm Ausgabe stimmt auch mit der vorherigen überein.
-
habe mal den Code in bochs ausprobiert, weiss nicht, ist es normal, dass nach dem Kommando pm lauter farbiger Zeichen erscheinen...
Das Progrämmchen war nur Spaß zum Testen, lief durch die Strings und wechselte die Farbe bei jedem 'NUL'. Ich bräuchte das hier:
Hat jemand einen ASM-Code für '.clearScreen' (ab 0xB0000) und '.eineSekundePause' in PM?
Dann könnte man dies hier machen:ProtectedMode2: mov ecx, 0x0B8000 mov esi, 0x10000 + msg_pm2 ; 'OS currently uses Protected Mode.' mov dl, 0x01 .endlessloop: call .eineSekundePause call .clearScreen inc dl cmp dl, 0x15 jz .resetcolor call PutStr_32 jmp .endlessloop .resetcolor: xor dl, dl jmp .endlessloop
Bestimmt nicht schlecht für den Anfang.
jmp word 0x8:ProtectedMode ;db 0xea ; instruction code for FAR JUMP ;dw ProtectedMode ; offset for jump ;dw 0x8 ; selector of the segment for the jump
Ja, geht! Offenbar gibt es bei manchen Compilerversionen Probleme, sonst würden nicht viele sich zu diesem Kunstgriff retten.
-
Die Subroutine ClrScr32 bewirkt einen Reboot. Kommentiert man den Befehl aus, läuft der String 'OS currently uses Protected Mode.' oben links in 16 Farben durch. Ich möchte nur jeweils vorher den Bildschirm löschen. Code macht aber Probleme. Vielleicht hat jemand eine Idee?
..
-
Im Tutorial könnte man den clrscr zunächst noch im RM ausführen. GDT habe ich
nach gdt.inc ausgelagert. Inzwischen alles schon ganz schön unübersichtlich.
So sieht momentan eine zumindest in Bochs binär von Platte funktionierende Version (von floppy im PC booten klappt momentan nicht?) aus:..