Discussion:
A20 geht nicht auf
(zu alt für eine Antwort)
Markus Wichmann
2006-09-07 16:02:50 UTC
Permalink
Hi all,
ich bin gerade dabei, einen Bootloader für mein OS zu schreiben (alles
noch in der Mache). Der Bootloader hat ja die Aufgabe, die CPU in den PM
zu versetzen, um dann den Kernel zu rufen. Bis es soweit ist, muss ich
erstmal das A20 öffnen (wenn ich alles richtig verstanden habe). Das
wollte ich mit folgender Prozedur tun.

openA20:
cli ;disable interrupts
mov cx,5
startAttempt1:
call wkc ;gotta wait for keyb controller
mov al,0d0h ;ask for status byte
out 64h, al ;send request
call wkd ;wait for data part
xor eax,eax
in al,60h ;fetch status byte
push eax ;safe eax
call wkc ;begin to grow roots while waiting for keyboard
mov al,0d1h ;ask to set status byte
out 64h, al ;send request
call wkc ;roots grow longer...
pop eax
or al,10b ;set A20 byte
out 60h,al ;hope it will eat it

call wkc ;again the roots grow...

mov al,0d0h ;ask for status byte again (is A20 now open?)
out 64h,al

call wkd ;wait for data part

xor ax,ax
in al,60h
test al,10b ;please, A20 bit, PLEASE
jnz .success ;if so: Hooray!!
dec cx ;else: try this another 5 times
jnz startAttempt1
mov si,A20FailureMsg ;you got this far? well, write error message
call putstr
call halt ; halt system
.success
mov si,A20SuccessMsg ;now write success message
call putstr
sti ;bring back interrupts
ret

Die Prozedur wkc holt sich von Port 64h den aktuellen Status und wartet,
bis bei diesem das Bit 10b gesetzt ist. wkd macht das gleiche, bloß
guckt es nach dem Bit 1b.
Die Prozeduren putstr und halt sollten selbsterklärend sein. Die Ausgabe
läuft ja auch korrekt. Trotzdem läuft irgendetwas schief: Ich erhalte
immer meine Fehlernachricht. Das Protokoll von Bochs ist leider etwas
/zu/ umfangreich: Ich kann mich nicht durchfitzen. Ob was dazu
drinsteht, weiß ich auch nicht. Ich habe einfach mal 32-Bit-Code
angeordnet. Ist doch OK, oder? Ausgeführt wird der Code ja.
Nehmt also einfach an, der Code würde auf einer Diskette im Bootsektor
laufen. Das ich einen x86 habe, brauche ich wohl nicht zu erwähnen ;-).
Mein Keyboard ist ein kabelloses am PS/2-Anschluss. Ist da A20 schon von
Anfang an offen/gar nicht berücksichtigt?
Und bevor ihr fragt: A20SuccessMsg und A20FailureMsg sind lediglich
sz-Variablen (ja sz. Dafür habe ich gesorgt.) Und putstr erwartet die
Basisaddresse des Strings in SI. (Ich überlege noch, ob ich nicht doch
auf Pascal-Strings umstelle, da mit C ja schon einmal ein OS geschrieben
wurde, mit Pascal hingegen noch nicht.)
Doch ich schweife ab, und davon geht A20 auch bloß nicht auf.
Was mache ich falsch?
Btw habe ich den obigen Code von
http://www.osdever.net/tutorials/a20.php?the_id=4 genommen und so
abgewandelt, dass ich immer die Prozeduren aufrufe, nicht in neu
erstellte Schleifen reingehe. (ist nicht so clever, immer den gleichen
Code selbst zu tippen, wenn es doch einmal Anspringen auch tut.)
tia und cya,
nullplan
--
To err is human. To forgive is divine.
To forget is also human...
Herbert Kleebauer
2006-09-07 18:20:54 UTC
Permalink
Post by Markus Wichmann
Hi all,
ich bin gerade dabei, einen Bootloader für mein OS zu schreiben (alles
noch in der Mache). Der Bootloader hat ja die Aufgabe, die CPU in den PM
zu versetzen, um dann den Kernel zu rufen. Bis es soweit ist, muss ich
erstmal das A20 öffnen (wenn ich alles richtig verstanden habe). Das
wollte ich mit folgender Prozedur tun.
Ist bei den neueren Rechnern das A20 Gate nicht standardmäßig
freigeschalten (bzw. nicht mehr vorhanden). Schreib halt
etwas bei 2 Mbyte in den Speicher und wenn dann das Gleiche
bei 3 MByte steht, muß du es wohl erst freischalten.

Zu 80486 Zeiten habe ich folgenden Code in meinem Debugger benutzt:


a20frei:
; Hinweis: Einlesen des 8042 Ausgangsports mittels des Befehls $d0,
; setzen des Bits 1 und anschliessendes zurueckschreiben mit
; $d1 funktioniert nicht. Problem liegt wohl bei Bit 4, das
; beim Lesen 0 ist, aber offensichtlich als 1 zurueckgeschrieben
; werden muss, da sonst die Tastatur keine Interrupts mehr
; ausloest (warum?). Deshalb wird zum Oeffnen des A20-Gates der
; Ausgangsport des 8042, unabhaengig von seinem alten Wert, mit
; $df (aus Literatur, wieso?) beschrieben.

move.l r0,-(sp)
move.w sr,-(sp)
bclr.w #9,sr ; Interrupt sperren

_10: in.b #$64,r0 ; Status Tastaturprozessor lesen
tst.b #2,r0 ; bereit fuer neuen Befehl?
bne.b _10 ; wenn nein, warten
move.b #$d1,r0 ; Code fuer Output-Port schreiben
out.b r0,#$64 ; Code an Tastaturprozessor

_20: in.b #$64,r0 ; Status Tastaturprozessor lesen
tst.b #2,r0 ; bereit fuer neuen Befehl?
bne.b _20 ; wenn nein, warten
; move.b #$dd,r0 ; A20-Leitung sperren
move.b #$df,r0 ; A20-Leitung freigeben
out.b r0,#$60 ; an Tastaturprozessor

_30: in.b #$64,r0 ; Status Tastaturprozessor lesen
tst.b #2,r0 ; bereit fuer neuen Befehl?
bne.b _30 ; wenn nein, warten

move.w (sp)+,sr ; Interrupt freigeben
move.l (sp)+,r0
rts.w
Markus Wichmann
2006-09-08 14:25:54 UTC
Permalink
Post by Herbert Kleebauer
Post by Markus Wichmann
Hi all,
ich bin gerade dabei, einen Bootloader für mein OS zu schreiben (alles
noch in der Mache). Der Bootloader hat ja die Aufgabe, die CPU in den PM
zu versetzen, um dann den Kernel zu rufen. Bis es soweit ist, muss ich
erstmal das A20 öffnen (wenn ich alles richtig verstanden habe). Das
wollte ich mit folgender Prozedur tun.
Ist bei den neueren Rechnern das A20 Gate nicht standardmäßig
freigeschalten (bzw. nicht mehr vorhanden). Schreib halt
etwas bei 2 Mbyte in den Speicher und wenn dann das Gleiche
bei 3 MByte steht, muß du es wohl erst freischalten.
; Hinweis: Einlesen des 8042 Ausgangsports mittels des Befehls $d0,
; setzen des Bits 1 und anschliessendes zurueckschreiben mit
; $d1 funktioniert nicht. Problem liegt wohl bei Bit 4, das
; beim Lesen 0 ist, aber offensichtlich als 1 zurueckgeschrieben
; werden muss, da sonst die Tastatur keine Interrupts mehr
; ausloest (warum?). Deshalb wird zum Oeffnen des A20-Gates der
; Ausgangsport des 8042, unabhaengig von seinem alten Wert, mit
; $df (aus Literatur, wieso?) beschrieben.
move.l r0,-(sp)
move.w sr,-(sp)
bclr.w #9,sr ; Interrupt sperren
_10: in.b #$64,r0 ; Status Tastaturprozessor lesen
tst.b #2,r0 ; bereit fuer neuen Befehl?
bne.b _10 ; wenn nein, warten
move.b #$d1,r0 ; Code fuer Output-Port schreiben
out.b r0,#$64 ; Code an Tastaturprozessor
_20: in.b #$64,r0 ; Status Tastaturprozessor lesen
tst.b #2,r0 ; bereit fuer neuen Befehl?
bne.b _20 ; wenn nein, warten
; move.b #$dd,r0 ; A20-Leitung sperren
move.b #$df,r0 ; A20-Leitung freigeben
out.b r0,#$60 ; an Tastaturprozessor
_30: in.b #$64,r0 ; Status Tastaturprozessor lesen
tst.b #2,r0 ; bereit fuer neuen Befehl?
bne.b _30 ; wenn nein, warten
move.w (sp)+,sr ; Interrupt freigeben
move.l (sp)+,r0
rts.w
Hi,
ich werd den Code mal testen. Melde mich dann wieder.
Tschö,
nullplan
--
To err is human. To forgive is divine.
To forget is also human...
Markus Wichmann
2006-09-13 16:05:25 UTC
Permalink
So, hab es jetzt mal getestet. Bisher wusste ich nicht, dass die "BITS
32"-Anweisung für einen Bootsektor tödlich ist. Jetzt weis ich es...
Ansonsten hat der Code gut funktioniert. Wenn man mal davon absieht,
dass ich erstmal Probleme mit der komischen Sprache von Herbert hatte
(also der Assembler-Sprache. Dein Deutsch war schon verständlich). Hab
einfach mal angenommen, r0 ist ein Register und alles, was da mit Rauten
davor dastand, sind Zahlenwerte. Dienen die drei ersten Zeilen alle dem
Löschen des Interruptflags? Da finde ich persönlich ein 'cli' einfacher
;-) Ich habe dem ganzen noch ein paar Testzeilen angefügt, um zu sehen,
ob man wirklich das A20 geöffnet hat. Ansonsten den Code nach Intel
übersetzt und unverändert übernommen. Klappt. Danke!
Nur versteh ich nicht, wieso du dreimal die gleiche Routine in den Code
schreibst, anstatt sie einmal zu schreiben, ein 'ret' dahinter zu setzen
und sie dann immer wieder zu rufen? Verbraucht viel weniger Platz (und
der ist bei einem Bootloader immer knapp)
cya,
und lass dich von meinen Fragen nicht zu sehr irritieren,
nullplan
--
To err is human. To forgive is divine.
To forget is also human...
Herbert Kleebauer
2006-09-13 17:12:12 UTC
Permalink
Post by Markus Wichmann
So, hab es jetzt mal getestet. Bisher wusste ich nicht, dass die "BITS
32"-Anweisung für einen Bootsektor tödlich ist. Jetzt weis ich es...
Ansonsten hat der Code gut funktioniert. Wenn man mal davon absieht,
dass ich erstmal Probleme mit der komischen Sprache von Herbert hatte
(also der Assembler-Sprache. Dein Deutsch war schon verständlich). Hab
einfach mal angenommen, r0 ist ein Register und alles, was da mit Rauten
r0 = eax, ax, al
r1 = edx, dx, dl
r2 = ecx, cx, cl
usw.
Post by Markus Wichmann
davor dastand, sind Zahlenwerte. Dienen die drei ersten Zeilen alle dem
Löschen des Interruptflags? Da finde ich persönlich ein 'cli' einfacher
00000000: 00000000: 66 50 move.l r0,-(sp)
00000002: 00000002: 9c move.w sr,-(sp)
00000003: 00000003: fa bclr.w #9,sr

eax und das Statusregister retten und dann Interrupts sperren. Und am
Ende dann:

0000001e: 0000001e: 9d move.w (sp)+,sr
0000001f: 0000001f: 66 58 move.l (sp)+,r0
00000021: 00000021: c3 rts.w

Beim Wiederherstellen des alten Statusregisters wird das Interrupt
Enable Flag wieder so gesetzt wie es vor dem Löschen war.
Post by Markus Wichmann
Nur versteh ich nicht, wieso du dreimal die gleiche Routine in den Code
schreibst, anstatt sie einmal zu schreiben, ein 'ret' dahinter zu setzen
und sie dann immer wieder zu rufen? Verbraucht viel weniger Platz (und
der ist bei einem Bootloader immer knapp)
Viel weniger Platz? Bist du sicher?

00000000: 00000000: e4 64 _10: in.b #$64,r0
00000002: 00000002: a8 02 tst.b #2,r0
00000004: 00000004: 75 fa bne.b _10
00000006: 00000006: b0 d1 move.b #$d1,r0
00000008: 00000008: e6 64 out.b r0,#$64

0000000a: 0000000a: e4 64 _20: in.b #$64,r0
0000000c: 0000000c: a8 02 tst.b #2,r0
0000000e: 0000000e: 75 fa bne.b _20
00000010: 00000010: b0 df move.b #$df,r0
00000012: 00000012: e6 60 out.b r0,#$60

00000014: 00000014: e4 64 _30: in.b #$64,r0
00000016: 00000016: a8 02 tst.b #2,r0
00000018: 00000018: 75 fa bne.b _30


Sind gerade mal zwei Bytes mehr als:

00000000: 00000000: e8 000e bsr.w sub
00000003: 00000003: b0 d1 move.b #$d1,r0
00000005: 00000005: e6 64 out.b r0,#$64
00000007: 00000007: e8 0007 bsr.w sub
0000000a: 0000000a: b0 df move.b #$df,r0
0000000c: 0000000c: e6 60 out.b r0,#$60
0000000e: 0000000e: e8 0000 bsr.w sub


00000011: 00000011: e4 40 sub: in.b #64,r0
00000013: 00000013: a8 02 tst.b #2,r0
00000015: 00000015: 75 fa bne.b sub
00000017: 00000017: c3 rts.w

Und für zwei Bytes mache ich nicht 3 Unterprogrammaufrufe.
Dirk Wolfgang Glomp
2006-09-14 09:41:25 UTC
Permalink
Post by Herbert Kleebauer
r0 = eax, ax, al
r1 = edx, dx, dl
Ich dachte "r1" wäre "ecx, cx, cl"...
Post by Herbert Kleebauer
r2 = ecx, cx, cl
usw.
...und "r2" wäre "edx, dx, dl"?

Bin verwirrt.

Dirk
Herbert Kleebauer
2006-09-15 08:32:45 UTC
Permalink
Post by Dirk Wolfgang Glomp
Post by Herbert Kleebauer
r0 = eax, ax, al
r1 = edx, dx, dl
Ich dachte "r1" wäre "ecx, cx, cl"...
Post by Herbert Kleebauer
r2 = ecx, cx, cl
usw.
...und "r2" wäre "edx, dx, dl"?
Bin verwirrt.
Ich hab halt versucht eine "logische" Nummerierung zu
verwenden. Und ich finde es halt sinnvoller edx r1 und
ecx r2 zu nennen als umgekehrt.
Dirk Wolfgang Glomp
2006-09-15 19:19:15 UTC
Permalink
Post by Herbert Kleebauer
Post by Dirk Wolfgang Glomp
Post by Herbert Kleebauer
r0 = eax, ax, al
r1 = edx, dx, dl
Ich dachte "r1" wäre "ecx, cx, cl"...
Post by Herbert Kleebauer
r2 = ecx, cx, cl
usw.
...und "r2" wäre "edx, dx, dl"?
Bin verwirrt.
Ich hab halt versucht eine "logische" Nummerierung zu
verwenden. Und ich finde es halt sinnvoller edx r1 und
ecx r2 zu nennen als umgekehrt.
Wo genau ist das logischer?

Dirk
Herbert Kleebauer
2006-09-16 17:45:31 UTC
Permalink
Post by Dirk Wolfgang Glomp
Post by Herbert Kleebauer
Post by Dirk Wolfgang Glomp
Post by Herbert Kleebauer
r0 = eax, ax, al
r1 = edx, dx, dl
Ich dachte "r1" wäre "ecx, cx, cl"...
Bin verwirrt.
Ich hab halt versucht eine "logische" Nummerierung zu
verwenden. Und ich finde es halt sinnvoller edx r1 und
ecx r2 zu nennen als umgekehrt.
Wo genau ist das logischer?
Wenn man ganz unvoreingenommen an die Sache heran geht,
denke ich es macht Sinn, die vier Byte adressierbaren und
die anderen vier Register zu gruppieren. Da esp als normales
Register kaum zu verwenden ist, ist es naheliegend, es mit r7
ganz hinten anzusiedeln. Damit ergibt sich bereits:

{r0,r1,r2,r3} = {eax,ebx,ecx,edx} und
{r4,r5,r6} = {esi,edi,ebp}
r7=esp

Nun, ich denke eax verdient die Nummer 0 zu sein:
manche Befehle funktionieren nur mit eax und andere
haben bei Verwendung von eax eine kürzere Codierung
als bei Verwendung anderer Register (z.b. add immediate).

Wenn eax=r0 ist, dann sollte edx=r1 sein, da diese
beiden Register in einigen Befehlen als Pärchen auftreten:

99 ext.l r0,r1|r0
ec in.b r1,r0
ee out.b r0,r1
f7 ff divs.l r6,r1|r0
f7 ef muls.l r6,r0,r1|r0

Da bei der 16 Bit Adressierung aus der ersten Gruppe nur
bx zur Speicheradressierung benutzt werden kann, ist es
logisch, ebx unmitelbar vor den anderen Registern die zur
Speicheradressierung benutzt werden können einzuordnen.
Damit ergibt sich:

eax=r0
edx=r1
ecx=r2
ebx=r3
esp=r7

Da bei meiner Synatx im Befehl die Quelle vor dem Ziel steht
(move.l src,dest) ist es auch logisch, esi vor edi einzuordnen.
Damit bleibt nur noch die Frage, wohin mit ebp. Da ebp wie esp
standardmäßig eine Adresse im SS und nicht wie bei den anderen
Registern im DS adressiert, könnte man ebp neben esp einordnen.
Adererseits ist gerade das der Grund, warum ich eigentlich ebp
nicht zur Speicheraddressierung verwende (da sonst eine Segment-
Override prefix nötig ist) sondern fast ausschließlich als
normales Datenregister. Und damit habe ich es als erstes der
zweiten Gruppe einsortiert. Damit ergibt sich ganz logisch:

eax=r0
edx=r1
ecx=r2
ebx=r3
ebp=r4
esi=r5
edi=r6
esp=r7
Dirk Wolfgang Glomp
2006-09-16 19:05:06 UTC
Permalink
Post by Herbert Kleebauer
Post by Dirk Wolfgang Glomp
Post by Herbert Kleebauer
Post by Dirk Wolfgang Glomp
Post by Herbert Kleebauer
r0 = eax, ax, al
r1 = edx, dx, dl
Ich dachte "r1" wäre "ecx, cx, cl"...
Bin verwirrt.
Ich hab halt versucht eine "logische" Nummerierung zu
verwenden. Und ich finde es halt sinnvoller edx r1 und
ecx r2 zu nennen als umgekehrt.
Wo genau ist das logischer?
Wenn man ganz unvoreingenommen an die Sache heran geht,
..machen wir.
Post by Herbert Kleebauer
denke ich es macht Sinn, die vier Byte adressierbaren und
die anderen vier Register zu gruppieren. Da esp als normales
Register kaum zu verwenden ist, ist es naheliegend, es mit r7
{r0,r1,r2,r3} = {eax,ebx,ecx,edx} und
{r4,r5,r6} = {esi,edi,ebp}
r7=esp
OK.
Post by Herbert Kleebauer
manche Befehle funktionieren nur mit eax und andere
haben bei Verwendung von eax eine kürzere Codierung
als bei Verwendung anderer Register (z.b. add immediate).
Klar das muß.
Post by Herbert Kleebauer
Wenn eax=r0 ist, dann sollte edx=r1 sein, da diese
99 ext.l r0,r1|r0
ec in.b r1,r0
ee out.b r0,r1
f7 ff divs.l r6,r1|r0
f7 ef muls.l r6,r0,r1|r0
Ah daher leitest du die beiden zusammen.
Post by Herbert Kleebauer
Da bei der 16 Bit Adressierung aus der ersten Gruppe nur
bx zur Speicheradressierung benutzt werden kann, ist es
logisch, ebx unmitelbar vor den anderen Registern die zur
Speicheradressierung benutzt werden können einzuordnen.
eax=r0
edx=r1
ecx=r2
ebx=r3
esp=r7
Dann ist das klar.
Post by Herbert Kleebauer
Da bei meiner Synatx im Befehl die Quelle vor dem Ziel steht
(move.l src,dest) ist es auch logisch, esi vor edi einzuordnen.
Damit bleibt nur noch die Frage, wohin mit ebp. Da ebp wie esp
standardmäßig eine Adresse im SS und nicht wie bei den anderen
Registern im DS adressiert, könnte man ebp neben esp einordnen.
Sehe ich ebenso.
Post by Herbert Kleebauer
Adererseits ist gerade das der Grund, warum ich eigentlich ebp
nicht zur Speicheraddressierung verwende (da sonst eine Segment-
Override prefix nötig ist) sondern fast ausschließlich als
normales Datenregister.
So mache ich es ebenfalls. Kann auch neben ecx als weiterer
Schleifenzähler gut verwendet werden.
Post by Herbert Kleebauer
Und damit habe ich es als erstes der
eax=r0
edx=r1
ecx=r2
ebx=r3
ebp=r4
esi=r5
edi=r6
esp=r7
Eigenwillig aber logisch. Schönen Dank werde ich jetzt beherzigen.

Dirk

Daniel Alder
2006-09-08 09:10:10 UTC
Permalink
Hallo Markus

Ich schreib dir nicht vor wie du's machen musst - schliesslich hab ich
auch mal so angefangen ;-)

Je nachdem was du machst kannst du deinen Kernel auch gleich so
verpacken, dass er mit den verbreiteten Boot-Managern GRUB bzw. ISOLinux
geladen werden kann. Dann hast du gleich von Anfang an ein
Boot-Verfahren, das so stabil ist, dass man es ohne grössere Tricks
sogar übers Netzwerk oder von CD verwenden könnte... Und wenn aus deinem
OS wirklich mal was wird, wird sich niemand über fehlende
Multiboot-Unterstützung ärgern.
Ich jedenfalls würde meinen nächsten Versuch so starten - wenns denn
einen gäbe :-)

Gruss
Daniel
Markus Wichmann
2006-09-08 14:17:35 UTC
Permalink
Post by Daniel Alder
Hallo Markus
Ich schreib dir nicht vor wie du's machen musst - schliesslich hab ich
auch mal so angefangen ;-)
Je nachdem was du machst kannst du deinen Kernel auch gleich so
verpacken, dass er mit den verbreiteten Boot-Managern GRUB bzw. ISOLinux
geladen werden kann. Dann hast du gleich von Anfang an ein
Boot-Verfahren, das so stabil ist, dass man es ohne grössere Tricks
sogar übers Netzwerk oder von CD verwenden könnte... Und wenn aus deinem
OS wirklich mal was wird, wird sich niemand über fehlende
Multiboot-Unterstützung ärgern.
Ich jedenfalls würde meinen nächsten Versuch so starten - wenns denn
einen gäbe :-)
Gruss
Daniel
Hi,
ich finde die Idee nicht so prickelnd, weil ich mal ausnahmsweise alles
selbst machen will. Sonst (bei normalen Apps) verlasse ich mich gerne
auf M$ bzw. die Autoren von FreePascal. Aber das hier soll _mein_ OS
werden. Nicht das von GNU oder Novell. Oder von irgendwem sonst.
Nebenbei ist eine Verwendung von CD doch das gleich wie von Diskette
oder Festplatte, oder? Momentan teste ich alles, indem ich Bochs ein
Diskettenimage als Bootfloppy gebe. Solange mein Kernel nicht die
Platzgrenzen sprengt, muss ich mir da auch keine andere Möglichkeit
einfallen lassen oder? (Weil mein FDD FUBAR ist, muss ich ein
Diskettenlaufwerk emulieren. Hat allerdings gedauert, bis einen Emu
gefunden habe). Außerdem ist der Kernel eh noch nicht aktuell -- erstmal
ist der Bootloader dran. Wenn der den PM angeschmissen gekriegt hat,
kann ich mich um einen Kernel bemühen. Aber bevor die Voraussetzungen
nicht gegeben sind, wäre es doch sinnlos, etwas darauf aufbauendes zu
proggen, oder?
Tschö,
nullplan
--
To err is human. To forgive is divine.
To forget is also human...
Daniel Alder
2006-09-09 15:46:11 UTC
Permalink
Hallo Markus
Post by Markus Wichmann
ich finde die Idee nicht so prickelnd, weil ich mal ausnahmsweise alles
selbst machen will. Sonst (bei normalen Apps) verlasse ich mich gerne
auf M$ bzw. die Autoren von FreePascal. Aber das hier soll _mein_ OS
werden. Nicht das von GNU oder Novell. Oder von irgendwem sonst.
Ist schon gut. Bei mir hat es so angefangen dass ich relativ früh schon
versucht hab den Kernel von einer Datei zu holen statt von einem
bestimmten Sektor. Das war mir dann aber schliesslich zu aufwendig für
den Anfang (wegen dem Dateisystem), und ich hab mir schliesslich ein
DOS-Programm geschrieben das den Kernel in den RAM lädt und in den PM
schaltet - mit einer eigenen "Übergabe-"Spezifikation.
Erst später hab ich dann erfahren, wie einfach ich mir diesen Schritt
mit Hilfe von GRUB hätte sparen können, und dann hätte ich mich schon
viel früher dem Multitasking widmen können.
Aber wie schon gesagt: Jeder darf natürlich bei 0 anfangen. Ist
vielleicht sogar ein notwendiger Schritt, um die notwendigen Kenntnisse
zu erlangen...

Übrigens: Booten von CD ist nur dann gleich, wenn du die
Floppy-Emulation verwendest. Ansonsten musst du dich mit einer ganz
anderen API und einem anderen Dateisystem rumschlagen...

Gruss und viel Erfolg ;-)
Daniel
Lesen Sie weiter auf narkive:
Loading...