Problem mit Kompiler für OS
-
Super. Dann werde ich das mal versuchen zum laufen zu bekommen. Danke!
-
Ich habe das jetzt mal versucht, aber ich weis nicht, wie ich das makefile aufrufen soll. Und eine kernel.map habe ich auch nicht. Und wie das Linkskript sein soll, weis ich auch nicht. Gibt es irgendwo eine Anleitung für "dumme"? Das mit dem kompilieren in der .bat Datei habe ich ja hinbekommen. Aber wie ich das jetzt mit dem makefile machen soll, weis ich leider nicht.
-
Gibt es irgendwo eine Anleitung für "dumme"?
Ich arbeite dran.
OK, das schaffst Du alles auf Dauer, ist in Summe leider nicht ganz unkompliziert, lohnt sich aber sich damit zu beschäftigen.
Also das makefile muss an deine Situation angepasst werden (einiges weg lassen) und wird mit mingw32-make ab Version 3.81 aufgerufen:
http://sourceforge.net/projects/mingw/files/make/makefile:
http://www.c-howto.de/tutorial-makefiles.html
http://www.ijon.de/comp/tutorials/makefile.html
http://www.cs.umd.edu/class/spring2002/cmsc214/Tutorial/makefile.htmlDas Linkerskript kernel.ld sollte so aussehen:
OUTPUT_FORMAT("binary") ENTRY(KernelStart) phys = 0x00008000; SECTIONS { .text phys : { *(.text) } .data : { *(.data) } .rodata : { *(.rodata) } .bss : { *(.bss) } }
... ist übrigens das gleiche wie das hier:
OUTPUT_FORMAT("binary") ENTRY(KernelStart) SECTIONS { . = 0x00008000; .text : { *(.text) } .data : { *(.data) } .rodata : { *(.rodata) } .bss : { *(.bss) } }
was ich "ordentlicher" finde.
Linkerskript:
http://tutorial.proggen.org/doku.php?id=kernel:tut:used_linkerscript
http://www.henkessoft.de/OS_Dev/OS_Dev2.htm#mozTocId920304 (Ende des Kernels bestimmen)Das kernel.map wird automatisch erzeugt durch das makefile:
LDFLAGS= -T kernel.ld -Map kernel.map
Ist eine brauchbare Sache, da Du exakt siehst, wo etwas gelandet ist, also wie Dein Kernel im Speicher aufgebaut ist.Wenn Du nicht klar kommst, ziehst Du dir diese zip-Datei:
http://www.henkessoft.de/OS_Dev/Downloads/20090703_61.zip
... und schaust Dir das alles genau an.Du hast hier jeweils auch in den User-Verzeichnissen makefiles.
Das läuft so, dass im Verzeichnis user_program program.asm zu program.elf umgesetzt wird.
Im Verzeichnis init_rd_img wird dieses Programm in initrd.img ins Filesystem eingebaut.
Das Image initrd.img wird mittels "incbin" in den Kernel transferiert (siehe process.asm) und dort weiter verarbeitet (-> RAM Disk / VFS -> elf-exec-File laden und in den User-Bereich schieben).Falls Du Fragen hast helfe ich gerne weiter.
-
Ich habe mir jetzt folgende .bat Datei erstellt.
SET PATH=C:\MinGW\bin;C:\msys\1.0\bin;C:\crosstools-complete\crosstools-complete\i586-elf\bin;C:\Programme\NASM;%PATH% mingw32-make makefile pause
Und dieses Makefile
SOURCES = kernel.asm $(filter-out boot.asm kernel.asm ,$(wildcard *.asm *.c)) OBJECTS = $(addsuffix .o,$(basename $(SOURCES))) ASFLAGSBIN= -O32 -f bin ASFLAGSOBJ= -O32 -f elf NASM = nasmw CFLAGS= -O -ffreestanding -fleading-underscore CC= i586-elf-gcc LDFLAGS= -T kernel.ld -Map kernel.map -nostdinc LD= i586-elf-ld all: boot.bin ckernel.bin make -s image boot.bin: boot.asm $(NASM) $(ASFLAGSBIN) $< -o $@ %.o: %.asm $(NASM) $(ASFLAGSOBJ) $< -o $@ ckernel.bin: $(OBJECTS) $(LD) $(LDFLAGS) $+ -o $@ image: cmd /c copy /b boot.bin + ckernel.bin MyOS del *.o del *.bin cmd /c rename MyOS MyOS.bin # $< Erste Abhängigkeit # $+ Liste aller Abhängigkeiten # $@ Name des Targets
Ansonsten habe ich noch boot.asm, kernel.asm und ckernel.c in meinem Ordner. Wenn ich jetzt aber die .bat Datei ausführe, meldet mingw32-make: Nothing to be done for 'makefile'. Was habe ich da falsch gemacht, bzw. nicht beachtet?
-
Nothing to be done for 'makefile'.
makefile ist im Gegensatz zu Batch-Dateien aufgabenorientiert. Bei Fehlern bricht es ab, und wenn alles schon besteht, macht es nichts und meldet dies.
Zieldateien löschen, und schauen, ob diese erstellt werden.
Übrigens sollte man - zumindest ab und zu - auch -Wall bei CCFLAGS einbauen, um zu sehen, was noch so an Ungereimtheiten existiert (manchmal z.B. UCHAR/CHAR).
-
Ich habe jetzt alle Sachen gelöscht, die er erstellen soll. Aber es kommt immer noch die selbe Meldung. Man muss doch aber die .c Dateien nicht selber kompilieren, oder?
-
Also so wie ich das gerade sehe, liegt es am "mingw32-make makefile".
Versuch es mal so:
SET PATH=C:\MinGW\bin;C:\msys\1.0\bin;C:\crosstools-complete\crosstools-complete\i586-elf\bin;C:\Programme\NASM;%PATH% mingw32-make pause
Denn make öffnet das makefile im aktuellen Ordner ja eigentlich schon standardmäßig.
-
Klappt's?
-
So, ich habe das von Deli1 mal ausprobiert. Scheint zu gehen, jetzt gibt es da nur noch irgendwelche Fehler, was das kompilieren mit nasm angeht, werde mich gleich mal darum kümmern, sobald ich etaws mehr weis, oder auch nicht, melde ich micht wieder.
-
So, das mit dem Assembler habe ich gelöst, war ein falscher Name schuld. Bei mir heißt er nämlich nasm und nicht nasmw. Jetzt häge ich gerade beim Kompilerproblem fest. Er meldet folgendes:
process _begin: CreateProcess(NULL, i586-elf-gcc -O -ffreestanding -fleading-unde rscore -c -o ckernel.o ckernel.c, ...) failed
-
So, irgendwie geht das jetzt, aber das makefile und die .bat verhalten sich noch etwas eigenartig. Da werde ich wohl noch mal dran arbeiten müssen. Aber immerhin bekomme ich jetzt mein HobbyOS.bin.
EDIT: Seltsame Verahlten habe ih ihm gerade abgewöhnt. Als letztes will ich jetzt noch von C zu C++ umsteigen. Wenn das geht, poste ich hier mal das abgeänderte makefile
-
Aber immerhin bekomme ich jetzt mein HobbyOS.bin.
Gut!
das makefile und die .bat verhalten sich noch etwas eigenartig.
make/makefile ist ein mächtiges Gespann, aber es macht auf Dauer Spaß damit zu fahren. Dran bleiben.
Kaum hat man beim OSDEV eine Sache gelöst, steht die nächste Herausforderung ins Haus. Lieber erst mal einfach anfangen und kleine Ziele setzen.
-
a) Warum benutzt ihr Makefiles in einem neuen Projekt und nicht eine der moderneren Alternativen
b) Wieso nicht die Autotools?
-
Das mit C++ habe ich verworfen, ist mir zu kompliziert. Ich benutzte jetzt nur C, ist ja sowie so die Standartsprache für OSDev.
Hier nun meine .bat Datei und das komplette makefile. Ich hoffe, es wird irgendwem Helfen, der vielleicht das selbe Problem hat wie ich.
Bat:SET PATH=C:\MinGW\bin;C:\crosstools-complete\crosstools-complete\bin;C:\Programme\NASM;%PATH% mingw32-make pause
Makefile:
SOURCES = kernel.asm $(filter-out boot.asm kernel.asm ,$(wildcard *.asm *.c)) OBJECTS = $(addsuffix .o,$(basename $(SOURCES))) ASFLAGSBIN= -O32 -f bin ASFLAGSOBJ= -O32 -f elf NASM = nasm CFLAGS= -O -ffreestanding -fleading-underscore CC= i586-elf-gcc LDFLAGS= -T kernel.ld -Map kernel.map -nostdinc LD= i586-elf-ld all: boot.bin ckernel.bin image boot.bin: boot.asm $(NASM) $(ASFLAGSBIN) $< -o $@ %.o: %.asm $(NASM) $(ASFLAGSOBJ) $< -o $@ ckernel.bin: $(OBJECTS) $(LD) $(LDFLAGS) $+ -o $@ image: cmd /c copy /b boot.bin + ckernel.bin HobbyOS.bin # $< Erste Abhängigkeit # $+ Liste aller Abhängigkeiten # $@ Name des Targets
-
Jetzt kommt der nicht in den CKernel. Auf dem Bildschirm steht immer nur diese bootloadermesage. Der CKernel:
void k_clear_screen() { char* vidmem = (char*) 0xb8000; unsigned int i=0; while(i<(80*2*25)) { vidmem[i] = ' '; i++; vidmem[i] = 0x07; i++; }; }; unsigned int k_printf(char* message, unsigned int line) { char* vidmem = (char*) 0xb8000; unsigned int i = line*80*2; while(*message!=0) { if(*message==0x2F) { *message++; if(*message==0x6e) { line++; i=(line*80*2); *message++; if(*message==0){return(1);}; }; }; vidmem[i]=*message; *message++; ++i; vidmem[i]=0x7; ++i; }; return 1; }; inline void outportb(unsigned int port,unsigned char value) { asm volatile ("outb %%al,%%dx"::"d" (port), "a" (value)); }; void update_cursor(int row, int col) { unsigned short position=(row*80) + col; // cursor LOW port to vga INDEX register outportb(0x3D4, 0x0F); outportb(0x3D5, (unsigned char)(position&0xFF)); // cursor HIGH port to vga INDEX register outportb(0x3D4, 0x0E); outportb(0x3D5, (unsigned char)((position>>8)&0xFF)); }; // Hauptprogramm int main() { k_clear_screen(); k_printf("Welcome to HenkesSoft OS.", 0); k_printf("The C kernel has been loaded.", 2); update_cursor(3, 0); // Endlosschleife des OS /*while(0) { };*/ return 0; };
Was habe ich da wieder falsch gemacht?
-
Zeige mal das Linkerskript und den Sprung nach _main in Assembler.
-
a) Warum benutzt ihr Makefiles in einem neuen Projekt und nicht eine der moderneren Alternativen
b) Wieso nicht die Autotools?http://de.wikipedia.org/wiki/GNU_Build_System
Hat jemand Erfahrungen damit?
-
Linkskript:
OUTPUT_FORMAT("binary") ENTRY(KernelStart) SECTIONS { . = 0x00008000; .text : { *(.text) } .data : { *(.data) } .rodata : { *(.rodata) } .bss : { *(.bss) } }
Kernel.asm:
[Bits 32] section .text ; ld needs that for coff format [global KernelStart] KernelStart: mov ax, 0x10 mov ds, ax ; data descriptor --> data, stack and extra segment mov ss, ax mov es, ax xor eax, eax ; null desriptor --> FS and GS mov fs, ax mov gs, ax mov esp, 0x200000 ; set stack below 2 MB limit [extern _main] ; entry point in ckernel.c call _main ; ->-> C-Kernel jmp $
-
... sieht unverdächtig aus. Schau mal nach kernel.map, ob da alles am rechten Platz gelandet ist, vor allem am Anfang bei 0x8000.
-
Memory Configuration Name Origin Length Attributes *default* 0x00000000 0xffffffff Linker script and memory map 0x00008000 phys = 0x8000 .text 0x00008000 0xfb *(.text) .text 0x00008000 0x1c kernel.o 0x00008000 KernelStart .text 0x0000801c 0xdf ckernel.o 0x00008041 _k_printf 0x0000801c _k_clear_screen 0x00008091 _outportb 0x0000809d _update_cursor 0x000080cb _main .data 0x000080fc 0x0 load address 0x000080fb *(.data) .data 0x000080fc 0x0 ckernel.o .rodata *(.rodata) .rodata.str1.1 0x000080fb 0x38 .rodata.str1.1 0x000080fb 0x38 ckernel.o .bss 0x00008134 0x0 load address 0x00008133 *(.bss) .bss 0x00008134 0x0 ckernel.o LOAD kernel.o LOAD ckernel.o OUTPUT(ckernel.bin binary) .comment 0x00000000 0x31 .comment 0x00000000 0x1f kernel.o .comment 0x0000001f 0x12 ckernel.o
Ich kann dort nichts finden!