Beiträge anzeigen

Diese Sektion erlaubt es dir alle Beiträge dieses Mitglieds zu sehen. Beachte, dass du nur solche Beiträge sehen kannst, zu denen du auch Zugriffsrechte hast.


Nachrichten - Jidder

Seiten: 1 ... 3 4 [5] 6 7 ... 81
81
Lowlevel-Coding / Re: In Videospeicher schreiben
« am: 03. May 2014, 02:02 »
Also wenn ich mal über das syntaktische Kauderwelsch hinwegsehe, dann ja. Ist dir klar, in welcher Reihenfolge die Bytes und die Nibbles in den Videospeicher geschrieben werden müssen? (Tip: Experimentell kriegt man das auch schnell raus.)
82
Lowlevel-Coding / Re: In Videospeicher schreiben
« am: 02. May 2014, 17:48 »
Hast du schon den Artikel dazu gelesen?
83
Offtopic / Re: Wie viele Adressen hat 1GB RAM?
« am: 30. April 2014, 19:34 »
Das ist die letzte Adresse bei 4 GB, aber die Frage war nach 1 GB.
84
Offtopic / Re: Wie viele Adressen hat 1GB RAM?
« am: 30. April 2014, 17:06 »
Das 0x vor der Zahl bedeutet, dass es sich um eine hexadezimale Zahl handelt. Entweder den dezimalen Wert ohne 0x oder den hexadezimalen Wert mit 0x schreiben. Außerdem bist du um eins daneben, weil die Zählung bei 0 beginnt. Das letzte Byte wäre also an Adresse 1073741823 bzw. 0x3fffffff.
85
Vermutlich sind meine Informationen darüber wie qemu sich verhält veraltet. Ich schreib hier auch immer nur dasselbe seit Jahren. Irgendwann geht halt die Zeit weiter ^^ Irgendwo im Handbuch von qemu ist das bestimmt dokumentiert.
86
Aus dem Log kann ich leider auch nichts interessantes erkennen. Eur erläuterung: Wenn du dir das Log mal anschaust, fällt dir sicherlich auf, dass sich die Blöcke darin immer wiederholen. Ein Block beginnt mit ein oder zwei Zeilen, die ein paar Informationen über den Interrupt liefern, und dann mehrere Zeilen Registerdump. Die ersten beiden Interrupts (SMM: enter und SMM: after RSM) treten in qemu immer auf, und haben nichts mit deinem OS zu tun. Der darauf folgende Interrupt ist interessant. Der Dump fängt mit
Zitat
check_exception old: 0xffffffff new 0xd
     0: v=0d e=0010 ...
Das ist der General Protection Fault (v=0d). Das e=0010 ist der Fehlercode und heißt in diesem Fall, dass es ein Problem mit dem Selektor 0x10 gibt. (Siehe auch Intel Manuals Volume 3, Chapter 6 Interrupt and Exception Handling, 6.13 Error Code.) Weiter unten steht
Zitat
GDT=     00104000 00000027
Das ist so zu interpretieren, dass wohl die richtige GDT geladen wurd (Adresse 0x104000) und diese auch groß genug ist (Limit 0x27). Bleibt also als einzige Fehlerursache nur noch der Inhalt der GDT. Also stimmt irgendwas mit set_gdt_entry nicht.

Und deswegen habe ich mir gerade nochmal den Code angeschaut und gesehen, dass du uint64_t als unsigned long definiert hast. Korrekt ist unsigned long long. Hätten wir auch eher rauskriegen können.
87
Der Zeiger ist wohl void, weil der Autor keine Lust hatte da was anderes zu nehmen. Hat keine besondere Bedeutung.

Kannst du auch keinen Fehler finden? :(
Nur durch Draufgucken auf den Code nicht.

Wie testest du den Code denn? Wenn du das mit qemu machst, kannst du mittels des Parameters -d int eine Log-Datei namens qemu.log erstellen lassen. Die landet unter Windows im aktuellen Verzeichnis und unter Linux in /tmp. Daraus kann man meistens mehr Informationen kriegen. Wenn du die Datei irgendwo hochlädst (Pastebin) oder wieder hier anhängst, kann ich mir die mal anschauen.
88
ok danke!
Ich hatte schon einmal in den Registern 0x10 drin. Dann habe ich etwas gegoogelt und ein beispiel mit 0x02 gefunden.
Welche Bedeutung hat dieses Register, und wieso muss ich es mit 0x10 laden?

Die Segmentregister müssen ja wissen, welcher GDT-Eintrag gemeint ist. Also erster, zweiter, dritter und so weiter. Außerdem gibt es im Segmentregister drei Bits, die unter anderem die Privilegstufe angeben. Das sind die drei unteren Bits im Register (also die Bits mit den Werten 1, 2 und 4). Erst die Bits darüber geben den Index an. Die Werte dieser Bits fangen bei 8 an, also im Prinzip wird die Eintragnummer mit 8 multipliziert.

Noch eine Frage: wieso ist der Datentyp des Pointers void*? Was bedeutet das?
Welchen Pointer meinst du?
89
Aber wenn ich den Prototyp der
Funktion, die für die Erstellung eines Eintrags zuständig ist, anschaue,
dann sind darin 2 unsigned und 1 normaler int enthalten.
Die Größe der Parameter ist nicht von Bedeutung. Die werden von der Funktion set_gdt_entry ja verarbeitet und nur bestimmte Bits davon landen auch wirklich in der GDT. Es muss also wirklich .limit = GDT_ENTRIES * 8 - 1 heißen.

Ein Problem, das ich so auf die schnelle im Code gefunden habe, ist, dass du die Segmentregister mit 0x02 lädst. Korrekt wäre 0x10, weil jeder Wert mal 8 genommen wird.
90
Offtopic / Re: Was kann Go?
« am: 25. April 2014, 01:25 »
Deine Fragen muss jemand anderes beantworten, aber zu deiner Beobachtung

ich hab gelesen das týndur nun neu erstellt wird, mit Googles Programmiersprache Go.

Schau mal auf das Datum des News-Eintrags ;)
91
Du musst prüfen, ob cin << zahl; überhaupt die eingabe verarbeiten konnte. Wenn der eingegebene Wert wie beispielsweise ein Buchstabe nicht in eine Zahl umgewandelt werden kann, kann in der Variable zahl auch nichts sinnvolles stehen. Der eingebene Wert ist offensichtlich ungleich eins, und somit wird immer b ausgegeben. Die Endlosschleife entsteht, weil er erneut versucht die Eingabe zu lesen, und diese wieder ungültig ist.

Nach einer Eingabe musst du also vor der Verarbeitung der Werte prüfen, ob diese eingelesen werden konnten. Dazu kannst du beispielsweise prüfen, ob cin.fail() false ist. Dann kannst du den Wert verwenden.
92
Das Wiki / Re: Tutorials veröffentlichen und mitwirken
« am: 22. April 2014, 15:17 »
Kommt natürlich auf deine Anforderungen an, die du an dein OS stellen willst. Aber ich rate erstmal zu FAT, weil es vermutlich einfacher ist als die anderen beiden und sowohl von Windows als auch Linux unterstützt wird.
93
Das Wiki / Re: Tutorials veröffentlichen und mitwirken
« am: 22. April 2014, 13:42 »
Ich vermute das hier ist gemeint. Das ist schon ziemlich zusammengeschustert und ich würde davon abraten sich davon inspirieren zu lassen.
94
Lowlevel-Coding / Re: GDT laden - Problem:
« am: 21. April 2014, 20:55 »
Theoretisch könntest du das. Dann ist es allerdings etwas komplizierter, wenn du auf die einzelnen Deskriptoren zugreifen willst, weil ein Deskriptor 8 Bytes groß ist, aber ein int ja nur 4 Bytes. Du müsstest also immer mit 2 multiplizieren, was den Code nicht gerade schöner macht.

Eine bessere Lösung als uint64_t wäre für die Deskriptoren ein richtiges struct zu definieren.

Beispielsweise ähnlich wie dies hier:
typedef struct gdt_descriptor {
uint16_t limit;
uint16_t base;
uint8_t base16;
uint8_t access;
uint8_t limit16;
uint8_t base24;
} __attribute__((packed)) gdt_descriptor_t;

Dann kannst du auf die meisten Elemente zugreifen ohne viel rumshiften zu müssen.
95
Lowlevel-Coding / Re: GDT laden - Problem:
« am: 21. April 2014, 20:08 »
Den Datentyp musst du selbst definieren. Das geht zum Beispiel mittels

typedef unsigned long long uint64_t;
oder du bindest den Standard-Header stdint.h ein, den der Compiler mitliefern sollte.

Edit: unsigned long long natürlich.
96
Lowlevel-Coding / Re: Wie die BDA auslesen
« am: 14. April 2014, 16:09 »
Ah, kleiner Geschichtsunterricht. Früher gab es mal die 8086-CPU, die halt 16-Bit-Register hatte und mittels Segmentierung immerhin 1 MB Speicher ansprechen konnte. (Technische Details hier). Ein paar Jahre später waren 1 MB nicht mehr genug, und Intel musste sich was einfallen lassen. Ich überspringe einfach mal die 286er und mach bei der 386er-CPU weiter. Diese CPUs waren endlich 32-Bit-CPUs und konnten damit bis zu 4 GB Speicher verwalten. Aber eine komplett neue CPU würde ja heißen, dass die alten Programme darauf nicht mehr laufen, also hat Intel sich was einfallen lassen. Wenn eine 386er-CPU gestartet wird, läuft sie zunächst in einem Modus, der kompatibel zu den 8086-CPUs ist. Dieser Modus heißt Real Mode. Das heißt die CPU kann zwar auch nur 1 MB Speicher verwenden, aber das BIOS und DOS und der ganze andere alte Mist aus den 80ern läuft darauf problemlos. Modernere 32-Bit-Betriebssysteme, die gerne 4 GB RAM nutzen wollen, schalten die CPU in den Protected Mode um. Dann funktionieren einige Dinge anders (zum Beispiel, die Bytes, die die CPU-Befehle kodieren haben jetzt eine leicht andere Bedeutung), und die Software muss entsprechend dafür geschrieben bzw. kompiliert sein, damit sie auch funktioniert, beispielsweise sind Zeiger 32-Bit groß statt 16-Bit.

Wir bewerben hier immer den Protected Mode gegenüber dem Real Mode, weil 4 GB RAM besser als 1 MB sind, Paging mehr kann als die Real-Mode-Segmentierung, das BIOS fast gar nichts cooles kann, was man nicht auch selbst im Protected Mode hinkriegt, es moderne 32-Bit-Compiler gibt, und Multitasking ohne Kopfschmerzen möglich ist. Wenn du einen Multiboot-fähigen Bootloader wie GRUB verwendest, befindet sich dein Kernel übrigens bereits im Protected Mode.
97
Lowlevel-Coding / Re: Wie die BDA auslesen
« am: 14. April 2014, 15:49 »
Hi,

Aber wie kann man denn die ganzen Adressen vom BIOS ansprechen um an die Information zu kommen?
Meine Idee ist mit *p auf die Adresse zu zeigen.

Genau das ist der Ansatz. Ich nehme an, dass du im Protected Mode bist. Dann kannst du beispielsweise die Größe des konventionellen Speichers, die sich an Offset 0x13 befindet, wie folgt auslesen:

char *bda;
unsigned short lowMem;

bda = (char *)0x400;
lowMem = *(unsigned short *)(bda + 0x13);

Beachte, dass ich da den Zeiger nach unsigned short * caste, bevor ich ihn dereferenziere, weil der Wert als WORD, also 2 Bytes, abgespeichert ist. Manche Sachen sind nur 1 Byte groß, die müsstest du dann nicht casten (bzw. auf unsigned char *). Das ganze kannst du natürlich nach deinen Vorstellungen von gutem Codestil auch anders schreiben.

Du klingst so, als hättest du eine Auflistung der Sachen, die man aus der BDA rauskriegt bereits gefunden. Ansonsten gibt es hier noch eine Liste, siehe auch Weblinks unten.

Das ganze möchte ich mit C++ machen, unter Assembler gibt es ja CPUID.
CPUID gibt übrigens nur Informationen über die CPU selbst aus (Hersteller, welche Features unterstützt werden, ...), nicht über die Hardware des PCs. Für das Auslesen unter C++ kannst du vielleicht sowas wie diesen Code verwenden: http://wiki.osdev.org/CPUID#Using_CPUID_from_GCC (dword = unsigned int). (Die BDA gibt übrigens auch nicht viel über die Hardware des PCs her. Auf dem PCI-Bus spielen sich heutzutage die interessanten Dinge ab.)
98
Kenne mich mit Raspberry Pi nicht aus, aber ich versuchs mal:

Zitat
Könnte es etwas mit "every 3 bits relates to a particular GPIO pin" zu tun haben? ... particular heisst ja besonders, aber was soll das bedeuten?
Ja, aber "particular" würde ich in diesem Fall eher mit "bestimmt" oder "jeweils" übersetzen.

Die ersten 4 Bytes gehören zu den ersten 10 Pins (0-9). Die nächsten 4 Bytes gehören zu den nächsten 10 Pins (10-19). Und so weiter.
In den 4 Bytes für Pins 10-19 gibt es jeweils 3 Bits pro Pin, also Bits 0-2 für Pin 10, Bits 3-5 für Pin 11, ... , Bits 18-20 für Pin 16, etc. Allgemein: Für Pin 10+x sind Bits 3*x bis 3*x+2 zuständig.

Ich hoffe das bringt etwas Klarheit.
99
Lowlevel-Coding / Re: GP-Fault beim schreiben von CR0
« am: 18. March 2014, 01:54 »
Also zwei Sachen fallen mir noch auf: Der Errorcode 0010 besagt, dass was mit dem GDT-Deskriptor 0x10 nicht stimmt. Möglicherweise ist was in der GDT nicht korrekt. Allerdings erklärt das nicht das übrige Verhalten (Wert in ESP).

Ich habe deswegen mal in meinen 64-Bit-Code geschaut, und mir ist aufgefallen, dass du in dem MSR Bit 31 (0x80000000) setzt. Korrekt wäre glaube ich Bit 8 (0x100). Möglicherweise erklärt das das komische Verhalten.

Wenn das funktioniert, landest du mit deinem Code übrigens im Compatibility Mode. (Falls dir das nicht bewusst ist.)
100
Lowlevel-Coding / Re: GP-Fault beim schreiben von CR0
« am: 17. March 2014, 23:32 »
Ist es gewollt, dass sich das Page Directory an Adresse 0x08000000 (CR3) befindet? Das ist nämlich 128 MB und soviel hat QEMU per default nicht. Wenn es nicht gewollt ist, liegt die Schuld vermutlich an der physischen Speicherverwaltung.
Seiten: 1 ... 3 4 [5] 6 7 ... 81

Einloggen