Eigenes OS?
-
..
-
..
-
Erhard Henkes schrieb:
Diese Funktion ist ebenfalls ein merkwürdiges Konstrukt:
page_t* get_page(ULONG address, UCHAR make, page_directory_t* dir) { address /= PAGESIZE; // address ==> index. ULONG table_index = address / 1024; // ==> page table containing this address if (dir->tables[table_index]) // table already assigned { return &dir->tables[table_index]->pages[address%1024]; } else if(make) { ULONG phys; dir->tables[table_index] = (page_table_t*) k_malloc( sizeof(page_table_t), 1, &phys ); k_memset(dir->tables[table_index], 0, PAGESIZE); dir->tablesPhysical[table_index] = phys | 0x7; // 111b meaning: PRESENT=1, RW=1, USER=1 return &dir->tables[table_index]->pages[address%1024]; } else return 0; }
hier ist eigentlich nur das letzte 'else' überflüssig.
-
(ULONG)-1 sollte man hier besser 0xFFFFFFFF schreiben?
Ich habe übrigens von James Molloy schriftlich die Freigabe, seinen - aus meiner Sicht nicht uninteressanten - Sourcecode als Basis für eigene Entwicklungen im Rahmen des Tutorials nutzen zu dürfen. Man muss ja nicht immer wieder das Rad neu erfinden, wie man so schön sagt.
Gerade die Verwendung des Bitsets beim Paging ist effizient. ..
-
mach ans ende der funktion return (ULONG)-1;
Ich habe das (ULONG)-1 aussterben lassen:
Sieht momentan - ohne Warnungen - so aus:
..hier ist eigentlich nur das letzte 'else' überflüssig.
Das mag sein, macht die Sache aber nur noch schlimmer.
-
Erhard Henkes schrieb:
mach ans ende der funktion return (ULONG)-1;
Ich habe das (ULONG)-1 aussterben lassen:
dann mach wenigstens eine #define aus 0xFFFFFFFF. vergisste mal ein F, dann kannste wieder schön lange fehler suchen.
Erhard Henkes schrieb:
hier ist eigentlich nur das letzte 'else' überflüssig.
Das mag sein, macht die Sache aber nur noch schlimmer.
wieso? einfach wech damit und return 0 ans ende. bleibt das gleiche.
-
Jeder hat seinen Stil.
-
Erhard Henkes schrieb:
Jeder hat seinen Stil.
ok, aber es soll doch ein tutorial sein. wenn du die funktionen ihrer lesbarkeit beraubst und eventuell dadurch fehler einbaust (z.b. i++ ist oft nicht das selbe wie ++i), dann machst du's dir und deinen lesern nur unnötig schwer.
-
An ein paar Klammern soll es wahrlich nicht scheitern:
..Mir gefällt das sprechende index u. offset aber besser als i und j.
Das große NFRAMES finde ich auch besser, weil konstant:ULONG NFRAMES = PHYSICAL_MEMORY / PAGESIZE;
Ich verwende das Präinkrement bevorzugt vor dem Postinkrement. In der for-Schleife spielt es keine Rolle.
Welches #define ... würdest Du denn für 0xFFFFFFFF verwenden? Da hat mich Dein Vorschlag sogar überzeugt, das könnte man noch austauschen, man nimmt wohl am besten das aus limits.h:
#define ULONG_MAX 4294967295UL also ULONG_MAX
-
Erhard Henkes schrieb:
An ein paar Klammern soll es wahrlich nicht scheitern:
alle daumen hoch^^
Erhard Henkes schrieb:
Mir gefällt das sprechende index u. offset aber besser als i und j.
das ist ok, aussagekräftige bezeichner sind immer gut, solange sie auch das richtige ausdrücken.
Erhard Henkes schrieb:
Ich verwende das Präinkrement bevorzugt vor dem Postinkrement.
naja, weil's dir vielleicht besser gefällt, aber für eine änderung gibt's keinen sachlichen grund, erst recht nicht, wenn der code vorher schon gut funktionierte. ich behaupte mal, die meisten c-programmierer benutzen eher das post-increment. mir jedenfalls sticht ein pre-increment immer ins auge und ich denke mir 'warum macht das hier jemand so? das hat mehr zu bedeuten, als nur die variable hochzuzählen'.
Erhard Henkes schrieb:
Welches #define ... würdest Du denn für 0xFFFFFFFF verwenden? Da hat mich Dein Vorschlag sogar überzeugt, das könnte man noch austauschen.
das 0xFFFFFFFF bedeutet hier doch 'ungültiger wert' oder sowas, dann könnteste es z.b. INVALID_VALUE o.ä. taufen.
btw, und was selbstdefinierte typen angeht: ULONG sieht aus wie ein #define (alles gross geschrieben). nimm doch als typedef uint32_t. das wäre dann sogar richtig modern, C99-mässig
-
Ich finde dieses angehängte _t für Standardtypen irgendwie lästig.
typedef unsigned int UINT; typedef unsigned char UCHAR; typedef unsigned short USHORT; typedef unsigned long ULONG; typedef signed char CHAR;
findet man in os.h. Schön ist dies wirklich nicht, aber auf jeden Fall kürzer als unsigned xxx. Zumindest habe ich nicht BYTE, WORD und DWORD verwendet.
Die Code-Einfärbung kennt dies auch noch nicht:
uint32_t zahl
Da mir Didaktik wichtig ist, wie sieht dies die Allgemeinheit?
-
Erhard Henkes schrieb:
Ich finde dieses angehängte _t für Standardtypen irgendwie lästig.
Wenn man primitiven Editor nutzt, dann ist es eben so, dass man alles selbst eintippen muss. Es gibt bekanntlich Alternativen
-
+fricky schrieb:
ich behaupte mal, die meisten c-programmierer benutzen eher das post-increment. mir jedenfalls sticht ein pre-increment immer ins auge und ich denke mir 'warum macht das hier jemand so? das hat mehr zu bedeuten, als nur die variable hochzuzählen'.
Dabei ist es doch genau umgekehrt, pre-incement zählt nur hoch, post-increment kann mehr bedeuten.
-
typedef unsigned int UINT; typedef unsigned char UCHAR; typedef unsigned short USHORT; typedef unsigned long ULONG; typedef signed char CHAR;
Besser mit Breite statt mit "Namen", z.B. UINT32, UINT16, usw.
Für mein Kompiler gilt dummerweise ULONG == UINT.
-
Ist das ein ernsthaftes Problem? Beim verwendeten DJGPP entspricht int nämlich 32 Bit.
printformat("Size of short: %d, int: %d, long: %d\n", sizeof(short), sizeof(int), sizeof(long));
Size of short: 2, int: 4, long: 4
-
Erhard Henkes schrieb:
Ist das ein ernsthaftes Problem? Beim verwendeten DJGPP entspricht int nämlich 32 Bit. ...
Für PC-Programmierer ist es wahrscheinlich kein Problem.
Bei dem Compiler, den ich grade verwende (verwenden muss ;)), ist z.B. sizeof(int) == 4 (32 Bit) und sizeof(long) == 5 (40 Bit)...
-
Bei dem Compiler, den ich grade verwende (verwenden muss ;)), ist z.B. sizeof(int) == 4 (32 Bit) und sizeof(long) == 5 (40 Bit)...
Danke für das Feedback. Momentan möchte ich diese Zahlen in den Typen vermeiden. Bei seltsamen Breiten von long kann man ja in os.h im typedef von long auf int umschalten, oders ehe ich das verkehrt?
Ich habe da noch eine Warnung im Compiler, bei der ich nicht ganz sicher bin, wie man sie am saubersten abschaltet:
ULONG fetchESP() { asm ( "mov %esp,%eax" ); }
Verwendung:
printformat("SS: %x, ESP: %x, EBP: %x\n", fetchSS(),fetchESP(),fetchEBP());
Warnung:
control reaches end of non-void function
Wie muss die Rückgabezeile aussehen? Ich möchte nicht void* als Rückgabewert verwenden, sondern ULONG, das in PrettyOS für 32-Bit-Speicheradressen Verwendung findet.
Selbe Frage wie hier: http://www.c-plusplus.net/forum/viewtopic-var-p-is-1697586.htmlIch habe mal folgendes probiert, was offenbar funktioniert, bin bei der AT&T Syntax nie ganz sicher, aber offenbar wird es langsam:
ULONG fetchESP() { register int eax asm("%eax"); asm volatile ( "movl %esp,%eax" ); return eax; }
Benötigt man hier movl oder geht auch mov? Ist asm volatile notwendig?
-
Noch ein Punkt: Ich möchte "Files" in die kommende "RAM disk" laden und dort mit dem virtuellen Filesystem bearbeiten. Dabei habe ich die Aufgabe eine bin- oder img-Datei von Floppy (hat nicht jeder) oder Festplatte (gefährlich bei Fehler) an eine feste Stelle im Speicher zu laden. Dies erfolgt typisch mittels GRUB, unser System soll ja aber ohne GRUB laufen. Welches Tool nimmt man da bei MS Windows in makefile, um ein file.img (sagen wir mal von Festplatte) sicher an eine bestimmte Stelle im RAM zu transportieren?
-
Erhard Henkes schrieb:
Danke für das Feedback. Momentan möchte ich diese Zahlen in den Typen vermeiden. Bei seltsamen Breiten von long kann man ja in os.h im typedef von long auf int umschalten, oders ehe ich das verkehrt?
Was ist dann der Sinn und Zweck von diesen Typdefinitionen... Man strebt eine gewisse Portabilität, z.B. mit der folgenden Typdefinition:
typedef long LONG;
weiss man immer noch nicht, wie viele Bits soll denn ein LONG sein? 32, 40 oder 64 Bit? Es geht ja nicht darum, den Typ long irgendwie zu verstecken, sondern "neue" Typen einzuführen, wo man genau weiss, dass sie so und so viele Bits breit sind.
Erhard Henkes schrieb:
Ich habe da noch eine Warnung im Compiler, bei der ich nicht ganz sicher bin, wie man sie am saubersten abschaltet...
Was würde dagegen sprechen, diese Funktion ganz in Assembler zu realisieren. Diese asm im Quellcode ist wie ein Dorn im Auge Wieder mal meine Phylosophie...
Also in Assembler z.B. so:.global _fetchESP .section .text _fetchESP: movl %esp, %eax ret
Assemblieren geht so:
as datei.s -o datei.o
Dann in irgendeiner Header Datei dem Compiler sagen, wie die Funktion aussieht:
extern uint32_t fetchESP(void);
Und die Objektdatei datei.o noch beim Linken angeben...
Erhard Henkes schrieb:
Benötigt man hier movl oder geht auch mov? Ist asm volatile notwendig?
Bei Befehlen, bei denen der Assembler erkennen kann, wie breit die Operanden sind, kann man l (steht für long) auch weglassen. Ich persönlich mach das nicht, weil defensive Programmierung usw.
-
Diese asm im Quellcode ist wie ein Dorn im Auge
Dank der AT&T Syntax sicherlich. Dafür hat es den Vorteil, dass man den Code im gleichen Modul betrachten kann. In obigem Fall sicher nicht so kritisch, da sprechende Funktionen.
In PrettyOS haben wir eine Mischung aus beidem, so dass der geneigte Leser/Entwickler selbst entscheiden kann, wie er es gerne hätte.