Lowlevel
Lowlevel => Lowlevel-Coding => Thema gestartet von: MrPerfekt am 13. May 2010, 10:55
-
hallo
Könnt ihr mir sagen was ich beim Linken falsch mache
ich habe eine Methode BootPoint und möchte diese als einstiebspunkt in mein Programm vestlegen
damit linke ich:
ld -static -melf_i386 -e BootPoint -o $bin/$entrypoint $bin/*.o &&
objcopy -R .note -R .comment -S -O binary $bin/$entrypoint $bin/entrypoint.bin || exit 1
-
Und was passiert?
-
asoo entschuldige das habe ich fergessen
usr/bin/ld.bfd.real: warning: cannot find entry symbol BootPoint; defaulting to 0000000008048074
/home/andreas/Desktop/BlackWindow/bin/kernel.o:(.eh_frame+0x12): undefined reference to `__gxx_personality_v0'
/home/andreas/Desktop/BlackWindow/bin/loader.o:(.eh_frame+0x12): undefined reference to `__gxx_personality_v0'
-
Du musst mit -fno-exceptions -fno-rtti kompilieren.
-
der tipp mit dem kompilieren hat geholfen
aber den startpunkt findet er trotzdem noch nicht
hättet ihr da auch noch eine idee
/usr/bin/ld.bfd.real: warning: cannot find entry symbol BootPoint; defaulting to 0000000008048094
-
Den hast du wahrscheinlich vergessen extern "C" zu deklarieren, siehe auch wiki (http://www.lowlevel.eu/wiki/C%2B%2B#C.2B.2B_Funktionen_aus_C.2FAssembler_nutzen). Ansonsten hast du die Funktion vergessen zu definieren oder linkst die entsprechende Objektdatei nicht hinzu.
-
Den hast du wahrscheinlich vergessen extern "C" zu deklarieren, siehe auch wiki (http://www.lowlevel.eu/wiki/C%2B%2B#C.2B.2B_Funktionen_aus_C.2FAssembler_nutzen). Ansonsten hast du die Funktion vergessen zu definieren oder linkst die entsprechende Objektdatei nicht hinzu.
Genau dass war mein fehler danke
aber es funktioniert noch nicht ganz
Hier nochmal eine zusammenfassung:
- Mein Bootloader Ladet ein paar sektoren in den Arbeitsspeicher
- Mein Bootloader Schaltet in den 32bit protected mode
- Mein Bootloader springt an das erste byte meines geladenen programmes
== Bis hier funktioniert alles danach nichts mehr
- das programm sollte 2 zeichen schreiben
- das programm ruft eine methode aus einem 2.ten programm auf
- diese methode hängt sich in einer endlosschleife auf
Ich compilliere mit
g++ -fno-exceptions -fno-rtti -Wall -m32 -Iinclude $i -c -o $o
linke mit
ld -static -melf_i386 -e BootPoint -o $bin/$entrypoint -Ttext 0x8000 $bin/*.o
und füge so mein programm an meinen bootloader
cat $bin/$boot.bin $bin/$entrypoint.bin > $bin/out.bin
Mein haupt cpp programm:
#include "loader.h"
#include "kernel.h"
void BootPoint()
{
int x = 1, y = 0;
char*videoPosition;
videoPosition = (char*)(0xB8000 + (y * 80 + x)*2);
*videoPosition = '=';
*((char*)(0xB8000)) = '=';
KernelMain();
}
und die dazugehörige .h datei
#ifndef _loader_h_
#define _loader_h_
extern "C" void BootPoint();
#endif // ifndef _loader_h_
-
Die obligatorische Frage: Warum meinst du einen eigenen Bootloader schreiben zu wollen/müssen? In 99% der Fälle willst du einfach GRUB nehmen. Es gibt mehrere Tutorials wie man das macht im Wiki, sogar eins mit C++.
Ansonsten müsste man den konkreten Sourcecode sehen oder die genauen Fehlermeldungen in einem Emulator mit Debugausgaben (z.B. bochs wenn man die Debugausgaben für "CPU0" hochschraubt, was man irgendwo im Konsolenmenü kann [zumindest die Linux-User]).
edit: Ich wette dein Bootloader versteht das ELF-Dateiformat nicht.
-
der bootloader funktioniert
ich habe bereits ein programm laden können welches nicht gelinkt worden ist
mein bootloader unterstützt noch kein dateiformat
das ist der grund warum ich meinen eigenen verwende
ok nicht nur das
mich interessiert es wie alles funktioniert
-
der bootloader funktioniert
Natürlich :roll:
Was meinst du wie viele das hier schon versucht haben glaubhaft zu versichern? Irgendwann glaubt man einfach nicht mehr an den "ich kopier mir was zusammen und das funktioniert ganz bestimmt in allen Lebenslagen ohne das ich irgendwas vom Bootloader verstanden haben muss und das ganze in 512Byte"-Bootloader.
edit: So wie das aussieht baut ld aber da eine ELF-Datei, oder? Kannst du ja per objdump nachprüfen. Wenn du kein Dateiformat im Bootloader implementiert hast, tut das natürlich nicht.
-
ok ich habe vielleich so begonnen
aber was herausgekommen ist wirst du nigenst im internet finden
(auser die professorische gdt)
(idt habe ich noch nicht implementiert)
da ich alles selbst geschrieben habe
edit: So wie das aussieht baut ld aber da eine ELF-Datei, oder? Kannst du ja per objdump nachprüfen. Wenn du kein Dateiformat im Bootloader implementiert hast, tut das natürlich nicht.
moment
noch einmal langsam
was meinst du
-
Du kannst dir eventuell auch mal das (http://www.lowlevel.eu/wiki/GRUB#Warum_GRUB.3F) durchlesen. Da stehen abgesehen von der obligatorischen Werbung für GRUB meinerseits auch ein paar Sachen drin die man über seinen Bootloader wissen sollte.
Ich meine, dass ld der ausgegebenen Datei ein bestimmtes Dateiformat verpasst, in dem Fall ist es ELF (Executable and Linkable Format, das Standarddateiformat für ausführbare Programme unter Unix). Das dient dazu, dass derjenige der die Datei lädt weiß, an welche Adresse es zu laden ist bzw. falls er es an eine andere Adresse laden will herausfindet welche Adressen (zB von Jumps/Calls, Zugriffen auf das Datensegment, etc...) er abändern muss. Außerdem wird die ausführbare Datei in Sektionen (Code, Daten) unterteilt, damit das Betriebssystem beispielsweise den Codebereich readonly und executable machen kann und den Datenbereich readwrite und non-executable.
-
ok dann kurz einen bootloader:
[ORG 07C00h] ;ab hier Startet das Programm
[bits 16]
jmp 0000h:start
start:
; Update the segment registers
mov ax, cs
mov ds, ax
mov es, ax
call print
;================================================================
;Lade das weitere Programm in den Arbeitsspeicher
;================================================================
reset: ; Reset the floppy drive
mov ax, 0 ;
mov dl, 0 ; Drive=0 (=A)
int 13h ;
jc reset ; ERROR => reset again
read:
mov ax, 0x0050 ; ES:BX = 0050:0000
mov es, ax ;
mov bx, 0x0000 ;
mov ah, 2 ; Load disk data to ES:BX
mov al, 5 ; Load 5 sectors
mov ch, 0 ; Cylinder=0
mov cl, 1 ; Sector=1
mov dh, 0 ; Head=0
mov dl, 0 ; Drive=0
int 13h ; Read!
jc read ; ERROR => Try again
;================================================================
;Das weitere Programm wurde in den Arbeitsspeicher geladen
;Schalte in den Protected Mode
;================================================================
[BITS 16]
cli ; Interrupts ausschalten
lgdt [gdtr] ; GDT Pointer laden
mov eax,cr0 ; In PMode wechseln, indem das niedrigste
or al,1 ; Steuerungsbit von cr0 geändert wird
mov cr0,eax ; muss über Umweg über ein anderes Register gemacht werden
jmp codesel:PMode ; FarJump zu einer 32-Bit PMode Funktion
[BITS 32]
PMode:
mov ax,datasel ; Segmentregister laden
mov ds,ax
mov ss,ax
mov esp,0x90000 ; Stack aufsetzen
mov eax, 1 ; Zeile
mov ebx, 0 ; Spalte
call print32
jmp 0x0500+512
;================================================================
;Das Programm ist nun im Protected Modus
;GDT
;================================================================
gdtr: ; Desktiptortabelle
dw gdt_end-gdt-1 ; Limit
dd gdt ; Basisadresse
gdt:
dd 0,0 ; Null-Deskriptor
codesel equ $-gdt
dw 0xFFFF ; Segmentgrösse 0..15
dw 0x0000 ; Segmentadresse 0..15
db 0x00 ; Segmentadresse 16..23
db 0x9A ; Zugriffsberechtigung und Typ
db 0xCF ; Zusatzinformationen und Segmentgrösse 16...19
db 0x00 ; Segmentadresse 24..31
datasel equ $-gdt
dw 0xFFFF ; Segmentgrösse 0..15
dw 0x0000 ; Segmentadresse 0..15
db 0x00 ; Segmentadresse 16..23
db 0x92 ; Zugriffsberechtigung und Typ
db 0xCF ; Zusatzinformationen und Segmentgrösse 16...19
db 0x00 ; Segmentadresse 24..31
gdt_end:
;================================================================
;GDT ende
;================================================================
;================================================================
; int2string (schreibt eax in den string)
; eax = number
;================================================================
[bits 16]
int2string:
PUSHA
LEA edi,[string]
MOV esi, edi
;MOV eax, 479
MOV ecx, 0x000A
startLoop:
MOV byte [edi], '0'
XOR edx,edx
DIV ecx
ADD [edi],edx
;MOV byte [edi], ebx
;ADD [edi],ebx
INC edi
CMP eax,0
JNE startLoop
MOV byte [edi],0
DEC edi
; vertausche die Richtung
switchLoop:
MOV ah, [esi]
MOV al, [edi]
MOV [esi], al
MOV [edi], ah
DEC edi
INC esi
CMP edi,esi
JA switchLoop
POPA
RET
;================================================================
; end int2string
;================================================================
;================================================================
; Print 16
;================================================================
string DB "Lade Black Window 0.0.0.0.0.0.0.6.0",0
print:
PUSHA
LEA bx,[string]
startOutLoop:
CMP byte [bx],0
JE ende
MOV ah,0eh
MOV al,[bx]
INT 10h
INC bx
JMP startOutLoop
ende:
MOV bh, 0
MOV ah, 03h
INT 10h
MOV ah, 02h
MOV dl, 0
INC dh
INT 10h
POPA
RET
;================================================================
; end Print
;================================================================
;================================================================
; Print 32
; eax = Line
; ebx = Position
;================================================================
[bits 32]
string32 DB "32 Bit Protected Modus geladen ",0
print32:
pusha
mov edx,0x50
mul edx
add eax,ebx
mov edx,0x2
mul edx
add eax,0xb8000
lea edx,[string32]
.paintloop:
mov cl,[edx]
mov byte [eax],cl
inc edx
add eax,0x2
cmp byte [edx],0
jne .paintloop
popa
ret
[bits 16]
;================================================================
; end Print
;================================================================
;================================================================
;Schreibe die Bootloaderidentifikation
;================================================================
times 440-($-$$) db 0
dq 0x00000000 ;Optional Disk Signatur
dw 0x0000 ;Usually Nulls
;Table of primary partitions
times 510-($-$$) db 0
bootloaderIdentifikation dw 0x0AA55
;================================================================
;ende Schreibe die Bootloaderidentifikation
;================================================================
aber wie kann ich den mit grub ersetzten
da müsste ich mir immerwieder einen grub auf mein img laden
-
aber wie kann ich den mit grub ersetzten
siehe zB. C++ Kernel mit GRUB (http://www.lowlevel.eu/wiki/C%2B%2B-Kernel_mit_GRUB) bzw. natürlich die OSDev für Einsteiger Serie (http://www.lowlevel.eu/wiki/Kategorie:OS-Dev_f%C3%BCr_Einsteiger), die C benutzt, aber dafür einiges mehr zu bieten hat.
da müsste ich mir immerwieder einen grub auf mein img laden
Korrekt, aber das ist unter Linux normal kein Problem (siehe zB hier (http://www.lowlevel.eu/wiki/GRUB#Siehe_auch)). Im Zweifelsfall bleibt immer der Ausweg ein vorgefertigtes Image (zB das von tyndur) herzunehmen und alles andere runterzuschmeißen.
edit: Was genau erwartest du von uns bezüglich des Quellcodes deines Bootloaders?
-
aber jetzt einmal angenommen mein bootloader funktioniert
(hat er ja bei programmen die nicht gelinkt werden gemacht)
dann müsst ja irgentwo noch ein fehler sein
-
Ja, du gibst ihm eine Datei im falschen Dateiformat. Wenn er den ELF-Header als Code ausführen will, kommt eben Mist raus.
-
Wie gesagt, dein Kernel hat ein Dateiformat, dass der Bootloader nicht versteht. Du kannst jetzt entweder den Kernel so Linken, dass er eine "flache Binary" ist (d.h. spezielles Dateiformat) oder deinem Bootloader das verwendete Dateiformat beibringen.
edit: Ich sollte vielleicht noch sagen, dass ersteres keine tolle Lösung ist.
-
asoo
jetzt verstehe ich
jetzt wird mir einiges klar
aber wie kann ich so linken das eine reine binare datei datei übrich bleibt
-
--oformat=binary zur Kommandozeile hinzufügen sollte das tun. Dann sollte allerdings dein Bootloader wissen an welche Adresse der Kernel gelinkt wurde, d.h. dann auch an welche Adresse er den Kernel zu laden hat.
-
danke danke danke
die header zu interpretieren versuche ich dann in meinem loader
danke nocheinmal
mrPerfket
-
ok irgentwie doch noch nicht
ich bekomme danach eine datei raus mit der ich nichts anfangen kann
weder mit objcopy noch direct als bin datei
-
Das objcopy macht auch keinen Sinn mehr auf eine "flache Binärdatei", insofern kannst du das sowieso weglassen. Ansonsten weiß ich nicht, was du damit gerne "anfangen" würdest. Wenn du das mal genauer spezifizieren könntest und dann auch noch sagst was dann passiert bzw. wieso es nicht geht, dann könnte man dir vielleicht helfen.
edit: Das Problem ist wahrscheinlich (wie ich oben schon erwähnt hatte), dass du ld nicht sagst, an welche Adresse der Code gelinkt wird. An genau diese Adresse muss der Bootloader dann auch den Code laden (sonst funktionieren absolute Jumps/Calls, Datenzugriffe, etc... nicht, was hoffensichtlich einsichtig sein sollte).
edit2: Was ganz wesentliches vergessen: Dein Bootloader weiß nicht an welcher Adresse innerhalb der Datei sich der Einsprungspunkt (also zB main) befindet. Das ist auch einer der Gründe warum man ungern auf ein Dateiformat verzichtet (wie bereits oben erwähnt). Aber mit irgendeiner weiteren Frickellösung kriegt man auch das hin.
-
sorry wenn ich nocheinmal störe
irgentwie kann ich mit dem file dass dabei rauskommt nichts anfangen
-
Vielleicht solltest du dann doch erstmal den einfachen Weg nehmen und GRUB benutzen.
Sich absichtlich für den schwereren Weg zu entscheiden, weil man eine Herausforderung sucht, ist schön und gut, aber dann darf man nicht erwarten, dass andere einem die Arbeit abnehmen. Wenn du dir einen anständigen Bootloader zutraust, solltest du auch deine Binaries halbwegs im Griff haben.
-
irgentwie kann ich mit dem file dass dabei rauskommt nichts anfangen
Wenn du Hilfe willst, dann solltest du sehr viel genauer erklären wo du ein Problem hast. Nichtmal meine Kristallkugel hilft mir da gerade weiter. :-D
-
Und, ohne dir zu Nahe treten zu wollen, ein bisschen Rechtschreibung (oder zumindest eine automatische Rechtschreibprüfung, Firefox hat sowas eingebaut) macht Posts grundsätzlich besser lesbar.
-
könnt ihr mir fl noch sagen warum ich mit dieser datei nichts anfangen kann
bzw wie ich es schaffe das der startpunkt mein 1. befehl ist
hab schon allemöglichen optionen ausprobiert und fiel gegoogelt
-
bzw wie ich es schaffe das der startpunkt mein 1. befehl ist
Indem du diejenige Funktion in eine eigene Sektion packst (siehe gcc-Dokumentation zu __attribute__((section("blub"))) (http://gcc.gnu.org/onlinedocs/gcc-4.5.0/gcc/Function-Attributes.html#Function-Attributes)). Dann brauchst du noch ein Linkerskript (siehe OSDev für Einsteiger bzw. das C++ mit GRUB Tutorial für Ideen). In diesem Linkerskript sollte dann die Sektion "blub" zu Beginn stehen, damit der Code deiner "Startfunktion" eben ganz am Anfang steht.
Aber wie bereits oben gesagt ohne richtiges Dateiformat kommen nur Frickellösungen raus, die dir irgendwann später wieder um die Ohren fliegen raus.
könnt ihr mir fl noch sagen warum ich mit dieser datei nichts anfangen kann
Ich sage es nochmals in hoffentlich ausreichender Deutlichkeit: Das ist keine (ausreichende) Problembeschreibung. Damit kann hier niemand etwas anfangen. Das ist genauso wie zu sagen meine Kaffeemaschine funktioniert nicht ohne dem Techniker zu sagen welche Marke oder Modell es denn wäre, was denn eigentlich nicht funktioniert und natürlich ohne die Kaffeemaschine überhaupt zur Reparatur mitzubringen.
-
sorry sorry
Ich hatte in Letzter Zeit viel stress.
Aber jetzt um einiges mehr Zeit.
Ich nehme nun einmal den guten ratschlag an und probiere das elf32 format in meinen Bootloader zu integrieren.
Ich melde mich ob es funktioniert hat.
Danke forerst einmal.