C++ Funktionsaufruf aus Bootloader

12/23/2014 11:06 RecK#1
Hey,

ich weiß nicht ob ich hier eine Chance auf eine Antwort habe,
aber ich versuche es dennoch.

Leider googlet man sich zu diesem Thema einfach "tod".
Es gibt gefühlt tausende Ansätze für die versch. Prozessrorarchitekturen,
mit oder ohne OS, versch. fertige Bootloader (grub, ..) usw. und so fort.

So aber nun mal "back to scratch"
Ich möchte für ein proof of concept projekt ein kleines OS schreiben.
Natürlich, sowie wahrscheinlich fast die meisten nicht gern in Assembler.

Die Entwicklung findet auf einem Linux-System statt.
Ein funktionierender Bootloader in Assembler x86_64 existiert bereits.
Compiliert wird die asm Datei mit nasm (binary output).

Die CPU Emulation erfolgt mit qemu-system x86_64.
Nun habe ich mehrmals gelesen, dass in Assembler via call eine "Funktion"
aufgerufen werden kann.


Also habe ich folgendes versucht (und auch oft im Internet gelesen):

kernel.cpp
Code:
void start_kernel() {
    // ...
}
boot_sect.asm
Code:
call start_kernel

; boot-loader
loop:
	jmp loop

times 510-($-$$) db 0 
;magic number
dw 0xaa55
Beim Compilieren kommt dann natürlich der Fehler "symbol start_kernel undefined"...Dann habe ich oft gelesen, man muss Assemmbler vorher mitteilen, dass s ein externer Funktionsaufruf ist, sprich mit extern start_kernel gekennzeichnet werden müsste. Nun kann ich aber in Assembler kein extern verwendet bei einem binary output (benötigt wegen bootloader, magic number) sondern müsste beispielsweise elf64 verwendet, womit ich aber "keinen Bootloader" mehr hätte... Oh man!

Habe auch einiges über das "linking" gelesen, allerdings meist spezifisch
für andere vorgefertigte Bootloader wie grub oder mit Verwendung von Linux oder windows...


Also meine gründsätzliche Frage ist nun:
Man muss doch sicherlich die c++ funktion irgendwo aus dem Speicher herraus über Assembler ansprechen oder? Wie genau klappt das, bzw erfolgt das nicht bei der compilierung der asm Datei oder beim Linking? Wie genau dieses Linking funktioniert weiß ich teilweise..zu mindestens wie ich mit gcc eine C++ "linke"... :S
Ich trete seit 2 Tagen nun einfach nur noch auf einem Punkt herum und komm nicht wirklich dahinter, wie ich nun vorgehen muss... Kann mir also evt. jemand sagen wie ich "möglichst primitiv" über Assembler x86_64 eine C++ Funktion ansprechen kann? Dabei ist zu beachten das das aufzurufende Assemblerscript gleichzeitig der Bootloader ist. Das ich in C++ dann sowas wie iostream oder fstream nicht verwenden kann ist mir bereits klar. Trotzdem ist es wenigstens lesbarere Code als Assembler. Denke auch das ein Kernel bzw OS in C++ deutlich schneller zu programmieren ist als eins mit Assembler :D

Hoffe mir kann dabei vielleicht jemand helfen.
Und bitte tut mir einen Gefallen, bevor ihr mir Links zu Google-Seiten schickt.
Lest sie euch bitte selber erst kurz durch ob das zu dieser Problematik passt.
Denn ich habe schon mehrere hundert Seiten offen gehabt :)
Eine Titelseite zu einem Problem sagt diesbezüglich leider meist wenig aus.



lg, frohe Weihnachten und schon mal frohes West.
Ist ja nicht mehr lang .. :handsdown:
12/23/2014 17:40 warfley#2
für gewöhnlich verwendet man für Betriebsysteme nicht C++ sondern C, da man bei der Kernel Entwicklung nicht auf OOP zurückgreift (ich glaube da das Halde/Keller system vom Betriebsystem implementiert wird, und ohne das OOP nicht möglich ist, weiß es aber nicht mehr genau)
Auf jeden fall habe ich mir mal ein sehr kleines Betriebsystem das in Pascal geschrieben wurde angesehen (FPOS) und da wurde einfach die Main Methode des Programms (Kernel.pas) verwendet, und es war nicht mal inline ASM nötig.

Aber ich muss dazu sagen, ich weiß nicht wie der Code der x86.pp aussah, die ist Bestandteil der rtl, da müsste aber wohl inline asm verwendet worden sein.

Auf jedenfalls worauf ich hinaus will, das Betriebsystem war aufgebaut wie ein ganz normales Programm, mit der Kernel.pas als Haupt datei und allen weiteren units als include units, und das ganze laden geschah im Ausführbaren part der Kernel.pas (in C also die Main Methode)


PS um nochmal auf deine Sache mit asm zurückzukommen, ein Linker ist ein Programm das verschiedene Kompilierte Dateien zusammenführt, der Linker ist dafür zuständig, dass wenn du eine Funktion Foo aus einem separaten Programm/Code(z.B. bar) dabei implementiert, diese in der Kompilierten Quelltextdatei (bar.o) zu finden und dann diese an dieser stelle "zusammenführen" damit man schlussendlich 1 Programm hat. Bis zum Punkt des Linkens weiß der Computer nicht, ob diese Funktion überhaupt in der Bar.o existiert, dafür ist der Linker verantwortlich
12/23/2014 20:50 Reav0r#3
Wo man dir sehr wahrscheinlich weiterhelfen kann : [Only registered and activated users can see links. Click Here To Register...]
Dort beschäftigt man sich fast ausschließlich mit dem Thema, also wenn du hier keine Antwort findest könntest du sicher dort mal fragen

Frohe Feiertage!
12/23/2014 22:16 YatoDev#4
ka ob es dir hilft aber es gibt ein paar in fasm geschriebene open source os.
die findest du im offiziellen flat assembler forum [Only registered and activated users can see links. Click Here To Register...]
solltest bestimmt auch kommentierten source finden aber bin mir nicht sicher ob dich das weiterbringt
12/24/2014 00:04 snow#5
#moved
12/24/2014 04:26 MrSm!th#6
Du müsstest sowohl deinen Assembler als auch deinen Compiler Object Dateien ausspucken lassen. Ein Linker muss diese dann zum Binary verknüpfen. Anders kannst du eine Funktion, die in einem C/C++ Modul implementiert ist, nicht sauber in einem ASM Modul aufrufen (genauer gesagt läuft das immer so ab, wenn du mehrere Übersetzungseinheiten hast, deine C++ IDE macht intern bei mehreren .cpp Dateien auch nichts anderes).
Mit Offsets und binärem Output kann eigentlich auch der Linker umgehen, weshalb der Bootloader trotzdem noch funktionieren sollte.

@warfley

C hat auch sowohl einen Stack als auch einen Heap und trotzdem kann man damit lowlevel programmieren. Das hat mit den technischen Gegebenheiten nichts zu tun. Man kann auch C++ zur OS Programmierung nutzen (habe auch schon ein Beispiel gesehen). Die Freispeicherverwaltung sowie die sichere Zuweisung von Speicher für den Stack muss man sowieso selbst implementieren, ob mit C oder C++ und beide Sprachen funktionieren ohne gleich gut oder schlecht bzw. primitiv.
12/30/2014 20:06 RecK#7
Danke MrSm!th.
Sprich ich werd mir das mit dem Linking nochmal ganz detailliert anschauen.
Muss ja auch von Beginn an wissen was da passiert :)
So weiß man wenigstens dass man nicht in die falsche Richtung geht.
"Anders kannst du eine Funktion, die in einem C/C++ Modul implementiert ist, nicht sauber in einem ASM Modul aufrufen"

Hatte bei den ersten Durchläufen immer Probleme mein Assembler Script zu compilieren,
da die Referenz nicht bekannt war. Aber dann ist das Problem ja logisch.

Schade das es zu C++ gemoved wurde.
Wusste nicht, dass ich ein C++ Problem habe, aber ok. Danke ;)
12/30/2014 23:24 MrSm!th#8
Na ja, ist eigentlich wirklich mehr ein allgemeines Problem und nicht direkt zusammenhängend mit C++. Aber ich würde mal behaupten, dass alle, die dir bei so einem Thema helfen können, auch hier mitlesen.

Mit der genauen Funktionsweise von Compiler und Linker solltest du dich sowieso befassen, wenn du ein OS schreibst. Der Linker lässt in der Regel viel Konfiguration für das Binary zu, insofern sind feste Offsets wie z.B. für die Magic Number wie gesagt kein Problem. Da der Bootloader nicht das letzte sein wird, was du in ASM schreibst, ist es ganz sicher nicht verkehrt, sich vor Augen zu führen, wie einzelne Module zusammengeklebt werden.