Hallo!
Ich bin neu in Sachen kernel development (und das hier ist mein erster Post) und Ich versuche gerade, Basiserkenntnisse zu erlangen und habe dafür einen ganz simplem Code von dem vieles gar nicht von mir ist sondern aus Tutorials gepostet. Leider bin ich auch in C nicht sonderlich erfahren (eher Java und VB .NET) und deshalb könnte es auch sein, dass mein Fehler nur ein Sprachenfehler ist. Also, jetzt das Problem: Ich habe zum Testen eine Funktion add die (wer hätte es gedacht?) zwei Zahlen addiert. Diese funktioniert auch prima, wenn Sie in meiner Haupt-C-Quelldatei 2kernel.c steht. Sinn der Funktion war es aber vor allem, auszuprobieren, wie Ich Funktionen auch in anderen Dateien ausführen kann. Dann liefert die Funktion aber plötzich nur noch den Wert 83. Hier mein Code, es wäre nett, wenn jemand mir einen Tipp geben könnte oder sagen könnte, wo vermutlich der Fehler liegt.
Loader.s:
global loader ; making entry point visible to linker
extern _kmain ; kmain is defined elsewhere
; setting up the Multiboot header - see GRUB docs for details
MODULEALIGN equ 1<<0 ; align loaded modules on page boundaries
MEMINFO equ 1<<1 ; provide memory map
FLAGS equ MODULEALIGN | MEMINFO ; this is the Multiboot 'flag' field
MAGIC equ 0x1BADB002 ; 'magic number' lets bootloader find the header
CHECKSUM equ -(MAGIC + FLAGS) ; checksum required
section .text
align 4
MultiBootHeader:
dd MAGIC
dd FLAGS
dd CHECKSUM
; reserve initial kernel stack space
STACKSIZE equ 0x4000 ; that's 16k.
loader:
mov esp, stack+STACKSIZE ; set up the stack
push eax ; pass Multiboot magic number
push ebx ; pass Multiboot info structure
call _kmain ; call kernel proper
cli
hang:
hlt ; halt machine should kernel return
jmp hang
section .bss
align 4
stack:
resb STACKSIZE ; reserve 16k stack on a doubleword boundary
2kernel.c:
extern int add(int a, int b);
int printstring (int line, const char * string){
unsigned char *videoram = (unsigned char *) 0xb8000;
int i;
int lines_written = 0;
for (i = 0; string != '\0' && i<80 * (25-line); i++) {
// Zeichen i in den Videospeicher kopieren
videoram[i * 2 + 80 * 2 * line] = string;
videoram[i * 2 + 1 + 80 * 2 * line] = 0x07;
}
lines_written = (i-(i%80)) /80 + 1;
return lines_written;
}
void printnr (int line, int offset, int nr){
int nr2 = nr;
int i = 0;
int nr3 = nr-nr%10;
int length = 0;
while(nr3 !=0){
length++;
nr3 = nr3-nr3%10;
nr3 = nr3 / 10;
}
if(length>1)offset--;
unsigned char *videoram = (unsigned char *) 0xb8000 + line *80*2 + offset*2;
char buf[10];
i=0;
while(nr2!=0){
buf = (nr2%10)+48;
i++;
nr2 = (nr2- (nr2%10))/10;
}
i=0;
while(i<=length*2){
videoram = buf[length - i/2];
videoram[i+1]=0x07;
i+=2;
}
//videoram=nr2+48;
return;
}
void kmain( void* mbd, unsigned int magic )
{
if ( magic != 0x2BADB002 )
{
/* Something went not according to specs. Print an error */
/* message and halt, but do *not* rely on the multiboot */
/* data structure. */
}
char * boot_loader_name =(char*) ((long*)mbd)[16];
char * command_line =(char*) ((long*)mbd)[4];
unsigned char *videoram = (unsigned char *) 0xb8000;
/* Write your kernel here. */
const char hw[] = "Hallo, Welt! 0.4.92";
int i;
//Clean Screen
for (i = 0; i<1999/*80*25 Zeichen -1 (wegen 0)*/; i++) {
// Zeichen i in den Videospeicher kopieren
videoram[i * 2] = 0;
}
printstring(0, hw);
printstring(1,"verwendeter Bootloader:");
printstring(2,boot_loader_name);
printstring(3, "Kernel:");
int l = printstring(4,command_line);
int lw = l;
l+=4;
l+=printstring(l , "Lines written:");
printnr(l++,1,lw);
int nr = add(33,55);
printnr(l++,1, nr);
return;
}
add.c:
int add(int a, int b){
return a+b;
}
linker.ld:
ENTRY (loader)
SECTIONS{
. = 0x00100000;
.text :{
*(.text)
}
.rodata ALIGN (0x2000) : {
*(.rodata)
*(.rdata)
}
.data ALIGN (0x2000) : {
*(.data)
}
.bss : {
sbss = .;
*(COMMON)
*(.bss)
ebss = .;
}
}
Zum Compilieren/Ausführen benutze ich folgendes Batch file:
2build.bat:
@echo off
echo build...
nasm -f elf -o 2loader.o 2loader.s
i586-elf-gcc -o 2kernel.o -c 2kernel.c -nostdlib -nostartfiles -nodefaultlibs
i586-elf-gcc -o add.o -c add.c -nostdlib -nostartfiles -nodefaultlibs
::i586-elf-ld -T 2linker.ld -melf_i386 2loader.o 2kernel.o add.o -o kernel
i586-elf-ld -T 2linker.ld -melf_i386 *.o -o kernel
echo Erstelle Floppy-image...
echo Leere Boot-Verzeichnis...
del /Q /F /S .\boot\floppy-build\*
cd boot
echo Kopiere Dateien in floppy-build...
copy E:\bin\grub4dos\grldr .\floppy-build\grldr
copy .\cfg\menu.lst .\floppy-build\menu.lst
copy ..\kernel .\floppy-build\kernel
echo Erstelle FAT-Dateisystem mit Daten...
bfi -t=144 -f=floppy.img floppy-build
echo ok
echo.
echo Bootsektor installieren...
E:\bin\grub4dos\bootlace.com --fat12 --floppy floppy.img
echo.
set u=u
echo Kopiere Floppyimage nach %u%:\usr\temp\christian\floppy\ ...
copy floppy.img %u%:\usr\temp\christian\floppy\floppy.img
echo.
echo Fertig!
pause
::echo running bochs...
::call "%userprofile%\desktop\bochs-ostest.bxrc"
::echo bochs has run
::pause>nul
cd ..
Ich vermute, dass es sich um einen Link-Fehler handelt. Wenn ich in build2.bat beim ld-Aufruf die Parameter 2kernel.o und add.o vertausche, stürzt das Programm übrigens bei der Ausführung in eine Endlosbootschleife. Wie gesagt, warscheinlich ist es irgendein dummer Fehler, bitte helft mir: ich probiere seit 2 Tagen rum und komm einfach nicht drauf.