Lowlevel
Lowlevel => Lowlevel-Coding => Thema gestartet von: bscreator am 18. October 2010, 19:56
-
Hallo,
ich versuche gerade verzweifelt, einen Kernel, welcher in C geschrieben ist, mit NASM zu laden.
Der ganze Bootloader-Code funktioniert, lediglich bei der Anweisung
call _main
bringt der NASM-Assembler die Meldung
binary output format does not support external references
.
Die Funktion main wurde im Kopf des Bootloaders mit EXTERN _main definiert.
Wo liegt der Fehler ?
Bootloader:
[BITS 16]
EXTERN _main
GLOBAL _boot
_boot db "Der erste C Kernel",13,10,0
org 0x7c00
start:
cli
mov ax,0x9000
mov ss,ax
mov sp,0
sti
xor ax,ax
mov ds,ax
mov ah,0x02
mov al,2 ;Anzahl zu lesender Sektoren
mov cx,2 ;Cylinder=0, Sektor=2
mov dx,0 ;Laufwerk=0=>Floppy
mov bx,0x0800 ;Kernel nach 0x0000:0x0800 laden
mov es,bx
int 0x13
call _main <- Diese Zeile kann NASM nicht ausführen
times 510-($-$$) db 0
dw 0xAA55
Kann ich den C-Kernel, wenn ich diesen auf den 2. Sektor einer Floppy schreibe und mit der Funktion 2 des INT 0x13 an Adresse 0000:0800 lade (wie oben beschrieben), eigentlich auch statt call _main
mit jmp 0000:0800
starten ?
Vielen Dank,
bsc
-
extern kannst du nur benutzen, wenn du die Dateien zusammenlinkst (und das wiederum heißt, dass du zumindest als Zwischenformat für die Objektdateien irgendwas wie ELF nehmen müsstest und keine flachen Binaries). Kernel und Bootsektor zusammenlinken ist natürlich Blödsinn.
Wenn das Laden korrekt funktioniert, nimm die jmp-Variante. So kurz wie dieser Bootsektor ist, bezweifle ich allerdings, dass er sehr zuverlässig ist. ;)
-
Da hast Du wahrscheinlich recht.
Nochwas:
Im Internet hab ich den folgenden Code gefunden:
[BITS 16]
EXTERN _main
start:
jmp 07c0h:main_entry
main_entry:
mov ax,cs
mov ds,ax
mov es,ax
cli
mov ss,ax
mov sp,9000h
sti
mov ah,02h
mov al,1
mov cl,2
mov ch,0
mov dl,0
mov dh,0
lea bx,[kernel] <-------------------------------------- Hier liegt der Fehler
int 13h
call _main
jmp $ ;
GLOBAL _prnt
_prnt:
push bp
mov bp, sp
push ax
push si
mov ax, [bp + 4]
mov si,ax
prnt1:
mov al,[si]
cmp al,0
JE prnte
inc si
mov ah,0eh
int 10h
jmp prnt1
prnte:
pop si
pop ax
pop bp
ret
GLOBAL _boot
_boot db "Der erste C Kernel",13,10,0
times 510-($-$$) db 0
dw 0aa55h
Beim Kompilieren kommt die Meldung, dass er das Label "Kernel" nicht kennt.
(Die Zeile lea bx, [kernel] ist markiert).
Im Skript gibt es lediglich eine Datei namens Kernel.cpp, aber sonst hab ich auch keine Ahnung, wo das kernel herkommt. So wie es ausschaut, lädt es die Adresse des Kernels. Aber damit kann doch nicht die Adresse der Kernel.cpp gemeint sein, oder ?
Vielen Dank für eure Hilfe,
bsc
-
Hi bsc,
direkt und ohne Umschweife empfehle ich dir dringenst: Schmeiß' den Code weg und lies dir das hier (http://www.lowlevel.eu/wiki/OS-Dev_f%C3%BCr_Einsteiger) durch und arbeite dich dadurch.
Grundlegende Dinge:
- Eigenen Bootloader schreiben ist ineffizienz und ein eigenes Projekt für sich, benutze lieber GRUB
- Code kopieren ist generell keine gute Idee (da sind schon so einige auf die Schnauze mit gefallen...)
Aber dennoch kurz zu deiner Frage:
kernel scheint eine Funktion zu sein, die irgendwo extern liegt.
Aber wie gesagt: Schmeiß' den Code weg und arbeite dich durch das Tutorial. Damit tust du dir einen großen Gefallen.
-
Hallo bscreator,
ich kann DemHartmut nur zustimmen und möchte noch ganz explizit auf den, im Wiki unter "Unverzichtbar" stehenden, Satz hinweisen:Auch die Zusammenhänge von Compiler - Assembler - Linker und den dazwischen liegenden Dateiformaten (linkbare Objekt-Dateien und ausführbare Programm-Dateien) sollten zumindest in Grundzügen geläufig sein.
An den Einsprungspunkt in den Kernel muss Dein Bootloader auf anderen Weg kommen, zusammenlinken geht auf jeden Fall nicht.
Grüße
Erik
-
Du musst zu deinem Kernel den Einsprungpunkt wissen. Schreibst du ihn in Sektor 2 der Floppy, dann brauchst du den Offset von Sektoranfang zu Einsprungpunkt.
(a) dein Kernel hat ein Executable Format (z.B. ELF), dann kannst du dort drin nachgucken, wo der is
(b) der Offset ist konstant (z.B. "das 4. Byte")
(c) der Offset wird durch eine Magic Number (z.B. "hinter dem ersten 0xDEADC0DE") markiert
Dein Bootloader muss diesen Offset jedenfalls ermitteln (oder die Konstante eingebaut kriegen) und dann per JMP genau auf diesen Punkt springen, der dein Einsprungpunkt im Kernel ist. Du kannst zur Laufzeit keine Quelltextlabels benutzen und flache Binärdateien kann man nicht verlinken. Außerdem sollte der Bootloader unabhängig vom Kernel sein.
Ansonsten: Ich empfehle Multiboot.
Gruß
-
Ok, dann werd ich den Code nicht verwenden.
Ich wollt bloß mal einen kleinen C-Kernel starten, der nichts anderes tut, als ne Message auf dem Bildschirm auszugeben, da ich vor langer Zeit mal was gefunden hab, wie man nen C-Kernel mit 16-Bit-ASM startet (da war auch JLOC dabei).
Aber wenn ich aus dem C-Kernel ne OBJ-Datei mach und diese in den 2.Sektor der Floppy kopier, muss ich nur noch die Adresse des Einsprungspunkts in dem C-Kernel wissen, oder ?
Jedenfalls vielen Dank für Eure Antworten,
bsc
-
Hallo,
Aber wenn ich aus dem C-Kernel ne OBJ-Datei mach und diese in den 2.Sektor der Floppy kopier
Also wenn ich das lese dann .......
Bitte beherzige meinen (unseren) Rat und beschäftige Dich erst mal mit den Basics.
Eine OBJ-Datei ist keine Flat-Binary, wo Du die hinspeicherst ist erst mal egal aber wenn Du die im Speicher hast und damit was machen willst musst Du die erst "decodieren". Schau Dir wirklich mal an wie ELF funktioniert!
Edit:
Multiboot ist im Prinzip auch eine Art Object-File-Format nur eben auf das absolut Nötigste (einen Einsprungspunkt und ein paar Flags) beschränkt.
Grüße
Erik
-
beschäftige Dich erst mal mit den Basics.
Die "Basics" sind für mich der Bootloader
ELF ist aber doch ebenso ein Crosscompiler, nur mit der "Einschränkung", dass damit nur PM-Betriebssysteme "bearbeitet" werden können.
Meine Favoriten sind aber immer noch die Real Mode-Betriebssysteme.
Also ist Multiboot auch ein Crosscompiler, oder?
Grüße,
bsc
-
ELF und Multiboot sind keine Compiler, weder cross noch anders, sondern Dateiformate.
Der RM ist absolut nutzlos, aber wenn du darauf bestehst, dann wirst du wahrscheinlich einen eigenen Bootloader brauchen.
-
Also ELF (und a.out und PE und LE und was es da noch so gibt) sind Dateiformate. Dadrin sind z.B. Flags, Einsprungpunkte, Teile/Sektionen definiert, die etwas über den Inhalt aussagen.
Multiboot ist eine Spezifikation, also eine Schnittstellenbeschreibung, wie ein Kernel mit dem Bootloader interagieren kann (d.h. dem Bootloader sagen kann, welche Umgebung er gern hätte und auch Informationen vom Bootloader bekommen kann). Dazu kommt eine Dateibeschreibung, damit der Bootloader mit dem Kernel und den Modulen auch etwas anfangen kann.
Mit dem Compiler hat das nichts zu tun, der erzeugt dir Object-Files (.o oder .OBJ oder sowas) - die sind abhängig vom Compiler! Die ELF-Datei erzeugt dir der Linker.
Beschäftige dich mal damit.
ELF ist übrigens auf keinen Prozessormodus festgelegt, Multiboot ist nur für den Protected Mode spezifiziert.
-
Hallo,
Multiboot ist nur für den Protected Mode spezifiziert.
Du meinst den x86-Proteced-Mode.
Aber es stimmt schon das MultiBoot nicht so ganz ein Executable-Datei-Format ist aber es gibt eben viele Gemeinsamkeiten.
All diese Dateiformate geben Auskunft darüber wie das Programm im Speicher aufgebaut sein soll, also an welche Stelle es in den virtuellen Adressraum soll, wie dieser virtuelle Adressraum aufgebaut sein soll und welche Dinge überhaupt aus der Datei auch in den Speicher sollen (z.B. Debug-Informationen werden meistens nicht in den Speicher des neuen Prozesses geladen). Das trifft alles im wesentlichen auch auf des MZ-EXE-Format von DOS für die Real-Mode-Programme zu.
@bscreator
Bitte beschäftige Dich wirklich mal damit!
Grüße
Erik
-
Du meinst den x86-Proteced-Mode.
Ich kenne keine nicht-x86-und-nicht-x86_64-Architektur, die einen "Protected Mode" besitzt. Die haben alle nur einen Modus.
-
Hallo,
Ich kenne keine nicht-x86-und-nicht-x86_64-Architektur, die einen "Protected Mode" besitzt.
Hm, könnte tatsächlich stimmen. Obwohl, hat der Itanium nicht irgend so einen x86-Emulations-Modus (da gibt es dann doch bestimmt auch den PM)?
Aber ich kenne eine nicht-x86-CPU-Architektur die einen "Real-Mode" hat, ätsch bätsch. :-P
Die haben alle nur einen Modus.
Also das stimmt nicht ganz, zwischen einem User-Mode und einem System/Supervisor/..../Gott-Mode können die meisten CPUs unterscheiden (meine ja auch).
Grüße
Erik
-
Die haben alle nur einen Modus.
Also das stimmt nicht ganz, zwischen einem User-Mode und einem System/Supervisor/..../Gott-Mode können die meisten CPUs unterscheiden (meine ja auch).
Meine Auch
-
Haarespalter.
Das zwischen User- & Kernelmodus (oder Supervisor) unterschieden wird, ist klar. Das meinte ich auch nicht. Und ein x86-Emulator kennt natürlich auch Real & Protected Mode, aber das ist für mich ganz klar x86 und nicht Itanums x86-Emulation oder Qemu unter ARM.
-
Hallo,
Wie gesagt, will ich immer noch meinen Bootloader selber schreiben und damit nichts anderes machen, als einen einfachen C-Kernel im REAL-Mode zu laden. Das tut mir leid, wenn ich vielen von euch mit dem
Bootloader selber schreiben
und dem
REAL-Mode
Kopfschmerzen bereite :-(
Was ist das Problem :
- die verschiedenen Dateiformate (Bootloader: Binary und Kernel: Object
Muss ich das ganze mit einem Crosscompiler machen, oder gibt es einen anderen Weg ?
(z.B. C-Kernel an 2. Sektor schreiben und an die Adresse springen)
Wenn ihr mir Code schickt, bin ich euch sehr dankbar.
Wäre wirklich sehr nett, wenn ihr mir helfen könntet.
Ich danke euch wirklich sehr, :-) :-)
bsc
-
Mit welchem Compiler arbeitest du denn um dein Ziel zu verwirklichen?
du brauchst einen der 16bit RM-Code ausspuckt.
sobald du den hast is das eig alles kein problem mehr, könnte man auch mit einem crosscompiler machen. die einfachste version wäre iwo MS dos zum laufen zu bringen(vllt geht das auch mit bochs oder so) und dir da so nen compiler drauf zu tun, gibt auch gleich viele gute assembler für DOS.
Musst dann aber drauf achten das du keinen DPMI compiler hast sondern einen der RM Code ausspuckt, mein Favorit ist Pacific C.
mfg
-
Hallo AGGROStar1991,
Ich verwende Turbo C. Bin mir auch fast sicher, dass der 16-Bit-Code ausspuckt.
Aber mit dem bekomme ich eben nur ne *.Object Datei.
Muss ich dann die Binary von NASM und die Object-Datei des Turbo C mit dem Crosscompiler verlinken, oder funktioniert es auch, wenn ich aus dem Bootloader-Code statt ner Binary ne Object-Datei mach und dann beide Object-Dateien mit NASM verlinke ?
Unter DOS zum Laufen zu bringen ist auch kein Problem, kann ja ne virtuelle Maschine erstellen und dann mein altes MS-DOS drauf installieren.
Vielen Dank,
bsc
-
also der Bootloader wird zu einer Flat Binary?
der C Kernel wird durch Turbao C zu ner .obj ?
Also verlinken nein.
.obj ist kein Dateiformat.
der crosscompiler hat mit deinem Problem erstmal nichts zu tun.
welches Dateiformat ist die .obj???
Wenn du das nicht selber herrausfinden kannst, lade die Datei mal irgednwo hoch.
PNoob
-
komm doch am besten mal in den IRC Channel #LOST @ irc.euirc.net.
Da kann man solche Sachen viel besser erklären.
-
Naja, aber wenn ich die OBJ-Datei und die Flat-Binary nicht verlinken kann, welche Dateiformate muss ich dann für den Bootloader und den C-Kernel wählen ?
Soviel ich weiss, kann man mit NASM auch OBJ-Dateien erstellen. Wenn man die NASM-OBJ und die Turbo-C-OBJ miteinander verlinkt, dann müsste es aber funktionieren, weil beide OBJ-Files 16-Bit-Code enthalten, oder ?
Gruss,
bsc
-
kann es sein, das du meinen Beitrag nicht gelesen hast? Wenn du keine Fragen beantwortest kann dir keiner richtig helfen.
Als Dateiformat nimmst du bei beiden Flat Binary.
PNoob
-
Naja, aber wenn ich die OBJ-Datei und die Flat-Binary nicht verlinken kann, welche Dateiformate muss ich dann für den Bootloader und den C-Kernel wählen ?
Der Bootsektor muss eine flache Binary sein. Für den Kernel kannst du wählen, was für ein Format du haben willst - der Bootsektor muss halt in der Lage sein, dieses Format zu laden. Wahrscheinlich willst du dafür also auch eine flache Binary haben.
Das ist aber jeweils nur das Ausgabeformat des Linkers. Wenn du die einzelnen Quellcodedateien erstmal in Objektdateien kompilierst und den Linker dann flache Binaries ausgeben lässt, dann sollte das klappen. Ob der Borland-Linker das mitmacht, weiß ich aber nicht auswendig.
-
Klar hab ich deinen Beitrag gelesen.
Der Bootsektor muss eine flache Binary sein.
Stimmt, hab ich vergessen
Als Dateiformat nimmst du bei beiden Flat Binary.
OK, wenn Du mir jetzt noch sagen kannst, wie man den 16-Bit-C-Kernel in eine BIN umwandeln kann, ist alles klar.
Gruss,
bsc
-
Du hast meinen Beitrag anscheinen d nicht gelesen. Wo sind die antworten auf meine Fragen?
komm mal nach #LOST
PNoob
-
Mit dem Compiler hat das nichts zu tun, der erzeugt dir Object-Files (.o oder .OBJ oder sowas) - die sind abhängig vom Compiler! Die ELF-Datei erzeugt dir der Linker.
Ich zitiere mich ja ungern selbst...
Die .OBJ, die dir Turbo C ausspuckt, ist in Borlands eigenem Format und kann somit an sich erstmal nur von Turbo C, TASM und TLINK verarbeitet werden. Ich behaupte einfach so, dass NASM ein anderes OBJ-Format verwendet.
Ich weiß nicht, ob und wie du mit Turbo C direkt eine flat binary erzeugen kannst, aber du kannst eine EXE-Datei erzeugen und diese mit EXE2BIN (gehört zu MS-DOS, eventuell auf der Supplement-Disk) in eine BIN umwandeln. Wie du mit der umgehen musst, kann ich dir aber nicht sagen, da musst du wahrscheinlich mit einem Debugger (DEBUG) drauf losgehen.
Turbo C ist wahrscheinlich auch nicht unbedingt das, was man heutzutage gern hätte. Allerdings gibt es nicht besonders viele Realmode-kompatible C-Compiler. Guck dir mal bin86/as86 an, mit dem wird ELKS (Embedded Linux Kernel Subset, ein Teil der Linux-API für 8086) entwickelt. Das wäre dann aber ein Linux-/Cygwin-Host.
Gruß
-
Hallo,
von der Benutzung von EXE2BIN kann ich nur abraten, das Tool funktioniert nur bei EXE-Dateien die keine Relokation beim laden benötigen und das dürfte auf Code von Compilern definitiv nicht zutreffen. Selbst bei kleinen Assembler-Programmen kann bereits diese Notwendigkeit auftreten. Wenn man das vermeiden will muss man schon genau wissen was man tut.
Als Alternative sollte man den Compiler/Linker anweisen eine COM-Datei zu erzeugen dann wird der Code gleich so generiert das keine Relokation erforderlich ist (und man ist auf das Memory-Model Tiny festgelegt).
Auf der anderen Seite ist ein EXE-Loader (für das MZ-EXE-Format von DOS) nicht allzu schwer das sollte sich mit weniger als 1kByte Code realisieren lassen, also noch im Rahmen eines kleinen Bootloaders liegen.
Der Bootloader selber muss aber zwingend eine simple Binärdatei sein weil das BIOS eben keine Relokation für den Boot-Sektor durchführt. Zusammenlinken von Boot-Loader und Kernel ist IMHO auch absolut unmöglich.
@ bscreator :
Du solltest dir aber wirklich erst mal das nötige Basiswissen über die Formate der OBJ-Dateien und der verschiedenen Executable-Formate anlesen!
Grüße
Erik
-
COM-Dateien werden beim Erzeugen reloziiert, und zwar fest auf die Adresse 0x100.
Das ist für den Bootloader unvorteilhaft. Zumal der aufgrund seiner geringen Größe noch in Assembler erstellt werden kann. (Wenn man Features braucht, die nicht-trivial sind, sollte man ohnehin einen anderen Bootloader verwenden.)
-
Hallo,
COM-Dateien werden beim Erzeugen reloziiert
Korrekt.
und zwar fest auf die Adresse 0x100.
Nicht korrekt.
Es ist das Offset 0x0100 in einem beliebigen Segment (der Code einer COM-Datei darf nicht vom Segment abhängen in dem er liegt, es werden also nur NEAR-Pointer benutzt).
Das ist für den Bootloader unvorteilhaft.
Das stimmt natürlich, aber ich meinte das eigentlich für den Kernel. Wenn der Kernel eine COM-Datei ist kann man den einfach überall in den 640k hinlegen und anspringen und er läuft.
Wenn man Features braucht, die nicht-trivial sind, sollte man ohnehin einen anderen Bootloader verwenden.
Was IMHO fast immer der Fall ist. Ich will ja nicht überheblich klingen aber reloziieren im Bootloader ist immer "nicht-trivial" (vor allem für Anfänger), das sollte man sich für den Kernel aufheben wenn man ne gute Basis hat und dann richtiges ELF o.ä. laden möchte. Außerdem erspart man sich mit der Verwendung eines vorhandenen/ordentlichen Bootloaders den ekligen x86-Real-Mode und das ganze BIOS-Gedöhns.
Grüße
Erik
-
Naja, die Adresse 0x100 ist trotzdem fest. Das mit dem Segment hatte ich nicht ausdrücklich hingeschrieben, stimmt natürlich.
Der Bootloader muss nicht reloziieren können, der Kernel kann ja an eine feste Adresse (z.B. 128K) geladen werden - die muss halt nur beim Linken des Kernels ebenfalls bekannt sein. Ich meinte mit nicht-trivial mehr so Informationen, die der Bootloader an den Kernel übergeben kann (von wo wurde gebootet, wo soll das Root-Dateisystem herkommen, Zeiger auf BIOS-Strukturen, ...).
Ansonsten: FULL ACK.
-
Hallo,
Naja, die Adresse 0x100 ist trotzdem fest.
Ich weiß Du hällst mich für einen Haarespalter aber die 0x0100 ist keine vollwertige Adresse sondern ein Offset, das muss man im Real-Mode immer explizit dazu sagen.
Der Bootloader muss nicht reloziieren können, der Kernel kann ja an eine feste Adresse (z.B. 128K) geladen werden - die muss halt nur beim Linken des Kernels ebenfalls bekannt sein.
Echt? Geht das auch bei ELF? Bekommt man da nicht doch irgendwo Probleme? Mir ist klar das der Linker, wenn er über alle Informationen das Loaders verfügt, auch die Aufgaben des Loaders mit übernehmen kann aber ich hätte nicht gedacht das er dann wirklich 100% vollständig reloziieren kann. Also mal wieder was gelernt.
Grüße
Erik
-
Wenn der Kernel eine flat binary ist, wird die beim Zusammenbauen ja ohnehin reloziiert, und zwar an eine fixe (Basis-)Adresse. Man muss "nur" Bootloader & Kernel aufeinander abstimmen.
Ob das bei ELF auch so leicht geht - keine Ahnung.
-
Die Dateien werden klar vom Linker erzeugt. Nur wenn ich von Compiler spreche, dann meine ich meinstens auch den Linker.
Linux-Umgebung hab ich auch nicht, bin nur Windows User.
Das mit der COM-Adresse ist der Offset 0x100, aber weiß nicht, wie das meinem Kernel helfen soll, eine Binary zu werden.
Also ihr meint, dass ich mir einen anderen RM-Compiler für C suchen sollte, der auf NASM "passt", oder ?
Habt ihr da Vorschläge oder Compiler(bzw. Linker), die ihr kennt ?
-
Ich hab mich jetzt mal ein bisl umgeschaut bzgl. NASM kompatiblen C-Compilern, aber leider noch keinen gefunden.
Zwar gabs einige für TASM und MASM aber NASM :?
Im Prinzip will ich ja nichts anderes, als einen C-Kernel vom Bootloader mit einem JMP-Befehl zu starten. Ich hab mal einen Tutorial
Beispielcode gefunden (glaub bei bonafide), der auch funktioniert hat. Da haben sie allerdings einen Crosscompiler verwendet.
Und das Tutorial such ich auch schon ewig, finde es nur nichtmehr.
Also gibts nur die folgenden 2 Möglichkeiten, oder ?
- Einen 16-Bit-C-Compiler (bzw. Linker) finden, der BINs erstellen kann
- Irgendwie mit einem Crosscompiler
Gruss,
Matthias
-
svenska, taljeth: jetzt mal nicht wieder aggressiv werden.
bscreator: du merkst, was es für ne Scheiß arbeit ist im Realmode nen OS zu schreiben? Es ist von uns allen ein gut gemeinter Rat dir GRUB zu nehmen, den Crosscompiler hier ausm Wiki und das OS-DEV für Einsteiger Tut durchzuarbeiten. dann hast du den 32 Bit Kernel, mit dem du viel mehr machen kannst. Ein weiterer Vorteil eines 32 Bit OSes ist, es programmieren bis auf wenige Ausnahmen alle 32/&4 Bit und daher können wir dir viel besser helfen. Ich will dir jetzt nichts einreden, sondern dich dazubringen deine Einstellung zu überdenken. Mich würde sowieso mal interressieren, was dich so am RM hält.
PNoob
-
Ja, RM ist Blödsinn, aber wenn er mehrfach sagt, dass er es trotzdem will, dann ist das zu akzeptieren.
Ich hab mich jetzt mal ein bisl umgeschaut bzgl. NASM kompatiblen C-Compilern, aber leider noch keinen gefunden.
Also mein nasm behauptet, das Format zu können, und zwar wenn man -fobj verlangt. Damit hast du dann alle Objektdateien im gleichen Format. Dann brauchst du aber auch noch einen Linker, der dieses Format kann und was passendes ausspuckt. tlink kann meines Wissens keine flachen Binaries produzieren, das heißt, dein Bootloader müsste einen .exe-Loader implementieren. Das wird zwar ein bisschen Arbeit kosten, dürfte aber machbar sein (die Frage ist allerdings, ob es mit deinem Wissensstand machbar ist - bedenke, dass sich von uns so gut wie keiner mit antiken Formaten beschäftigt und wir dir deshalb nur beschränkt helfen können).
Du kannst dir auch noch einen anderen Linker suchen, der OMF liest und Flat Binaries ausspuckt. Ich kenn keinen, aber Google hilft dabei sicher.
Also gibts nur die folgenden 2 Möglichkeiten, oder ?
- Einen 16-Bit-C-Compiler (bzw. Linker) finden, der BINs erstellen kann
- Irgendwie mit einem Crosscompiler
Weißt du, was ein Crosscompiler ist? Wenn ja, erklär mal, was er mit deinem Problem zu tun hat. Das ist mir nämlich ein wenig rätselhaft. ;)
-
Du wiederholst dich, PNoob. Im RM brauchst du übrigens keine nennenswerten Treiber schreiben (du nutzt die des BIOS) und dein OS läuft auch auf 8086ern noch. Das sind konkrete Vorteile. Die Nachteile kennen wir ohnehin alle. Zudem behaupte ich, dass ein RM-Betriebssystem einfacher zu schreiben ist als eins für den PM, solange deine Anwendungen und der Kernel nicht größer werden als 64K.
Zum Thema:
Du brauchst vorerst keinen Crosscompiler, da du ja von i86 auf i86 kompilierst und dein Zielbetriebssystem selbst baust. Crosscompiler wird erst interessant, wenn du neben dem Kernel auch eine libc für dein OS hinreichend fertig hast und Anwendungen bauen möchtest.
Zum Turbo C passt bevorzugt der TASM, die anderen werden wahrscheinlich schwieriger sein und/oder ein anderes OBJ-Dateiformat benutzen.
Du musst "irgendwie" deinem Turbo C beibringen, dass es eine flat binary erzeugt und diese an eine bestimmte Adresse linkt. Das kann eine BIN sein, das kann aber auch eine COM sein (wenn du mit der Adresse "BeliebigesSegment:100h" und dem Model=Tiny leben kannst).
Crosscompiler von DOS für i86 wirst du vermutlich nicht finden, am ehesten bin86 (Linux-Host) oder ACK (Amsterdam Compiler Kit, Minix-Host).
Schlussfolgerung, eh mir PNoob nochmal in den Nacken springt: Entweder du befasst dich mit Turbo C soweit, bis du ihn dazu bringst, Dinge zu tun, die du gern getan haben möchtest - oder du wechselst den Compiler. Ich glaube, dass du zu TC keine große Dokumentation mehr finden wirst, außer der damaligen/mitgelieferten oder einem alten Fachbuch aus der Uni-/FH-Bibliothek deines Vertrauens. Die haben sowas meistens.
Wenn du deinen Kernel an eine bestimmte Adresse gelinkt hast UND er eine flat binary ist, dann muss dein Bootloader diesen Kernel an exakt dieselbe Adresse laden und kann ihn dann per JMP ausführen.
Solltest du konkrete Fragen haben, melde dich. Ansonsten betrachte ich zu diesem Thema erstmal alles gesagt. Gibt sonst nur Ärger.
Nach kurzer Recherche überrascht mich, dass TLink angeblich keine flatbinaries erstellen kann, Quelle hier (http://superfrink.net/athenaeum/OS-FAQ/os-faq-linker.html). Dort gibt es aber viele Linker zur Auswahl. Schon der erste klingt nicht soo schlecht. ;-) Damit musst du dich aber selbst beschäftigen.
Gruß,
Sebastian
-
Alos Treiberprogrammierung ist natürlich eine Sache, die man im PM amchen muss, aber ansonsten ist es, da er ja snscheinend eh liber mit C schreiben will im PM um einiges leichter.
PNoob
-
@Svenska: Auf der Seite bin auch gelandet. Und die scheint ein bisschen irreführend zusein: Was tlink nämlich kann, ist COM. Und das würde ich durchaus als flache Binary deklarieren. Also halb so schlimm und man müsste auch mit nasm/Turbo C/tlink was funktionierendes hinbekommen.
-
Naja, COM würde ich eher als subset der flat binary bezeichnen... gibt halt noch ein paar Unterschiede (die Einsprungadresse ist festgelegt auf 0x100 [ja ich weiß, Segment ist egal] und die Größe des Gesamtsystems ist auf 64K beschränkt).
Daher überrascht mich das doch etwas, dass man das dann nicht einstellen kann. Was solls. Für den Anfang sollte COM jedenfalls reichen.
Und was C mit dem PM zu tun hat, erschließt sich mir nicht. Wenn du jetzt wenigstens gesagt hättest, Treiberprogrammierung in C++ macht sich leichter, gut, Geschmackssache, aber der war...naja.
-
So meinte ich das auch: COMs sind flache Binaries, auch wenn nicht alle flachen Binaries COMs sind. Aber eine echte Einschränkung ist das ja für den Anfang nicht. Und später braucht man sowieso ein ordentliches Binärformat, da macht dann auch eine flache Binary ohne diese Einschränkungen keinen Spaß mehr...
-
was für anständige Binärformat gibtes denn, die mit der Segmentierung klar kommen? ELF scheidet ja aus zwei gründen aus, ersten nur für 32 und 64 Bit geeignet und es kommt laut erik mit segmentierung nicht klar.
-
Ich hab mich damit nicht näher beschäftigt, aber ich schätze, .exe wird wohl tun, wenn DOS das verwendet hat.
-
Das Executable-Format muss eigentlich keine Segmentierung unterstützen, solange man die einzelnen Bestandteile des Programms (also die Sektionen) unter der Maximalsegmentgröße hält, also im RM unter 64K. Dann braucht man nur die Sektionen als Segmente behandeln und gut ist.
EXE gibt es in verschiedenen Geschmäckern, von denen nicht alle geeignet sind:
MZ (DOS-16bit)
LE (Win16-VxD und OS/2)
LX (OS/2) [ungeeignet, LX=Linear eXecutable]
NE (Win16)
PE (DOS-32bit/Win32) [nur 32-Bit]
Nach hier (http://en.wikipedia.org/wiki/Relocatable_Object_Module_Format) ist OBJ sogar standardisiert. (Asche auf mein Haupt, ich dachte, das wäre ein Borland-exklusiv-Format.)
Außerdem gibt es das a.out-Format, welches die frühen Unixe verwendeten; der Nachfolger COFF ist fast eine PE-EXE.
Gruß,
Svenska
-
Hallo,
das MZ-EXE-Format von DOS sollte auch für größere RM-Programme (die für Code und Daten jeweils mehrere Segmente benötigen) sehr gut tauglich sein. Der Code zum relozieren dürfte IMHO recht wenig sein aber ich schau mir da gerne noch mal die Spec an (falls ich die noch mal finde).
Ich hab mal einen Boot-Sector für FAT12/16/32 entwickelt der eine EXE aus dem Stammverzeichnis lädt (bis max 512kB, beliebig fragmentiert) und dann aus dem Header den Einsprungspunkt ermittelt und eben anspringt. Das ganze hat in die gut 400Bytes gepasst und es fehlte nur der Code zum relozieren (der hätte aber auch nicht mehr rein gepasst, den von der EXE gewünschten Stack habe ich ebenfalls ignoriert). Ich denke es wäre möglich den Code zum relozieren in die EXE selber zu packen, man müsste nur ein kleines Assemblermodul dafür bauen und dessen Einsprungspunkt beim Linken angeben, dieser Code muss dann die EXE-Datei im Speicher durchgehen und an den gewünschten Stellen modifizieren und als letztes dann den Einsprungspunkt der crt0.asm anspringen (dieser Sprung darf sogar von der Relozierung abhängen). Das Problem ist das diese EXE dann auch im Speicher fest liegt also eventuell nur noch recht wenig Speicher, von den 640kB, für weitere User-Mode-Programme übrig bleibt.
was für anständige Binärformat gibtes denn, die mit der Segmentierung klar kommen?
Wenn Dir das MZ-EXE-Format von DOS nicht gefällt bleibt noch das NE-EXE-Format von Windows 2/3 übrig aber das bietet IMHO nur wenig bis gar keine Vorteile was die Speicheraufteilung angeht.
ELF scheidet ja aus zwei gründen aus, ersten nur für 32 und 64 Bit geeignet und es kommt laut erik mit segmentierung nicht klar.
Ich kann nicht mit Sicherheit behaupten das ELF absolut nicht mit Segmentierung zurecht kommt aber es dürfte wohl ziemlich aufwendig sein die Segmentierung in ELF hinein zu prügeln, ein eigenes Format mit passenden Loader macht IMHO signifikant weniger Arbeit. Einen eigenen Linker bräuchte man eh da keiner der Linker die ELF können ein ELF mit Segmentierung erzeugen kann.
Das Executable-Format muss eigentlich keine Segmentierung unterstützen, solange man die einzelnen Bestandteile des Programms (also die Sektionen) unter der Maximalsegmentgröße hält, also im RM unter 64K. Dann braucht man nur die Sektionen als Segmente behandeln und gut ist.
Also ganz so optimistisch sehe ich das nicht, man benötigt auch Relozierungen bei denen nur die Segmentnummer (oder Selector im PM) eines bestimmten anderen Segmentes irgendwo eingetragen wird. Genau solche Dinge fehlen bei ELF & Co.
Grüße
Erik