Lowlevel

Lowlevel => Lowlevel-Coding => Thema gestartet von: Pk3 am 19. August 2009, 17:39

Titel: C - Kernel wird nicht geladen
Beitrag von: Pk3 am 19. August 2009, 17:39
Hallo, ich versuche schon seit Stunden meinen C Kernel zum laufen zu bringen.
Einen Bootloader habe ich schon gemacht, der in den ProtectMode schaltet, wenn ich aber dann in den Kernel springen will passiert garnichts.

Hier mal der Bootloader:

[BITS 16]
        org 0x7c00

        %define STACKSEGMENT  0x9000                ; lineare Adresse des Stacks  : 0x90000
        %define STACKSIZE     0x200                 ; Größe des Stacks            : 512Byte
        %define KERNELSEGMENT 0x10000               ; lineare Adresse des Kernels : 0x40000

        jmp START
 
GDTR:
 limit  dw              (GDT_END - GDT - 1)
 base   dd              (0)

GDT:
NULL_DESCRIPTOR EQU $-GDT
        dd              0
        dd              0
CODE_DESCRIPTOR EQU $-GDT
        dw              0ffffh
        dw              0
        db              0
        db              09ah
        db              0cfh
        db              0
DATA_DESCRIPTOR EQU $-GDT
        dw              0ffffh
        dw              0
        db              0
        db              092h
        db              0cfh
        db              0
GDT_END:

START:
        cli                                         ; keine Interrupts
        mov             ax,        STACKSEGMENT
        mov             ss,        ax               ; Stacksegment setzen
        mov             sp,        STACKSIZE        ; Größe des Stacks festlegen
        xor             ax,        ax               ; ax = 0
        mov             ds,        ax               ; Datensegment auf 0 setzen
        sti

        xor             bx,        bx               ; Ziel-Offset         : 0x0
        mov             ax,        KERNELSEGMENT    ; Ziel-Segment        : 0x4000
        mov             es,        ax
        mov             ah,        0x2              ; Funktion 0x2        : Sektor lesen
        mov             al,        1                ; Anzahl der Sektoren : 1
        mov             ch,        0                ; Track               : 0
        mov             cl,        2                ; LSN                 : 2
        mov             dh,        0                ; Head                : 0
        mov             dl,        0                ; Laufwerk            : A
        int             0x13                        ; Interrupt           : 0x13
 
        cli                                         ; keine Interrupts
        mov             ax,         cs              ; Code-Segment holen
        mov             ds,         ax              ; Daten-Segment gleichsetzen
        xor             eax,        eax             ; ax = 0
        mov             es,         ax              ; Extra-Segment auf Null setzen
 
        mov             si,         GDT             ; Quelle : GDT
        xor             di,         di              ; Ziel : 0x0000
        mov             cx,         6               ; 6 DoubleWords kopieren (ganze GDT)
        rep             movsd

        lgdt            [GDTR]
 
        mov             eax,        cr0
        or              eax,        1               ; Bit0 setzen (PE-Bit enabled)
        mov             cr0,        eax

        db              0xea                        ; FAR-JUMP zum Codesegment
        dw              (PMODE)
        dw              0x8
 
        [BITS 32]                                   ; 32 Bit-Code erstellen
 
PMODE:
        xor             eax,        eax
        mov             eax,        2               ; Selektor für das Datensegment erstellen
        shl             eax,        3
 
        mov             ds,         ax              ; Daten-, Stack- und Extrasegment mit
        mov             ss,         ax              ; Datensegmentdeskriptor laden
        mov             es,         ax
        xor             ax,         ax
        mov             fs,         ax              ; fs und gs mit Nulldeskriptor laden
        mov             gs,         ax
        mov             esp,        09000h         ; Stack setzen

jmp             08h:010000h

stop:
jmp stop

        times 512-($-$$)-2 db 0
        dw 0x0AA55

Der Kernel (*.c)

int begin()
{
char *Text = "Welcome to Protected Mode";
char *VideoMem = (char*)0xA8000;

while(*Text) 
{
*VideoMem = *Text; 
*VideoMem++; 
*VideoMem = 7; 
*VideoMem++; 
*Text++; 
}

return(0);
}

Linker-Script (*.ld)

OUTPUT_FORMAT("binary")
INPUT("kernel.o")
ENTRY(_begin)
SECTIONS
{
  .text  0x10000 :
  {
    *(.text)
  }
  .data  :
  {
    *(.data)
  }
  .bss  :
  {
    *(.bss)
  }
}

Und so mach ich das ganze zu einer IMG-Datei.

nasm -f bin -o boot.bin boot.asm
gcc -ffreestanding -c -o kernel.o kernel.c
ld link.ld -o kernel.bin

copy /b boot.bin + kernel.bin os.img

Weiß jemand woran das liegt das der Kernel nicht geladen wird?
Hab schon viel rumprobiert, z.B. die Addresse dess Kernels,
hat alles nichts geholfen  :-(.

Bitte um Hilfe!
Titel: Re: C - Kernel wird nicht geladen
Beitrag von: SHyx0rmZ am 19. August 2009, 17:48
Ich glaube, das ist jetzt nicht alles, was falsch ist, aber da kann sicher jemand mit mehr Ahnung weiterhelfen (Kein Plan vom Linken  :-D), aber:

Dein größter Fehler besteht zuerst einmal darin, dass dein Bootloader den Kernel aufrufen muss. Nur weil du Bootloader und Kernel im/auf dem Image hast, tut sich da nix. Dein Bootloader muss halt einen call oder einen jmp (Ja gut, es gibt auch andere Möglichkeiten) machen, damit dein Kernel auch überhaupt aufgerufen wird. Dafür sollte dem Bootloader auch der Einstiegspunkt des Kernels bekannt sein.

Eventuell solltest du dir nochmal ganz genau visualisieren, wie der Programmfluss denn abläuft, dann klappt das auch ;-)

PS: Bevor ichs vergesse und irgendjemand Anderes es loswerden will: Wir empfehlen GRUB als Bootloader.


Uppala, da hab ich doch glatt was überlesen...
Titel: Re: C - Kernel wird nicht geladen
Beitrag von: Jidder am 19. August 2009, 18:00
Hi,

%define KERNELSEGMENT 0x10000 Das soll wohl 0x1000 sein, wenn ich mir den Rest des Codes anschaue. Mein NASM 2.02 hat mir deswegen auch eine Warnung gegeben.

char *VideoMem = (char*)0xA8000;Der Videospeicher ist bei 0xB8000. Der Wert 0xA8000 stammt aus einem total verkorkstem Tutorial.

An das Ende von begin() muss außerdem eine Endlosschleife, weil du aus der Funktion nicht zurückkehren darfst. Du bist ja mit jmp dahin gesprungen.

Zitat
ld link.ld -o kernel.bin
Da muss ein -T vor das link.ld.
Titel: Re: C - Kernel wird nicht geladen
Beitrag von: Pk3 am 19. August 2009, 19:13
Zitat
Der Videospeicher ist bei 0xB8000. Der Wert 0xA8000 stammt aus einem total verkorkstem Tutorial.

Achso, na dann kein Wunder das nix auf dem Bildschirm kommt :).

Zitat
An das Ende von begin() muss außerdem eine Endlosschleife, weil du aus der Funktion nicht zurückkehren darfst. Du bist ja mit jmp dahin gesprungen.

Ich hab nach diesem Jump zum Kernel ein "Endlossjump" gemacht also

stop:
jmp stop

Funktioniert doch auch, oder?

Zitat
Da muss ein -T vor das link.ld.

Wenn ich das mache, bekomme ich folgende Fehlermeldung:

ld: cannot perform PE operations on non PE out put file 'kernel.bin'.

Den rest werde ich verbessern und mal schaun obs geht.
Danke für die Antworten  :wink:!
Titel: Re: C - Kernel wird nicht geladen
Beitrag von: XanClic am 19. August 2009, 19:56
Ich hab nach diesem Jump zum Kernel ein "Endlossjump" gemacht also

stop:
jmp stop

Funktioniert doch auch, oder?

Nein, da du den Kernel mit "jmp" aufgerufen hast, er weiß also nicht, wohin er zurückkehren soll. Um das zu korrigieren, müsstest du "call" verwenden. :wink:
Titel: Re: C - Kernel wird nicht geladen
Beitrag von: Jidder am 19. August 2009, 19:57
Ich hab nach diesem Jump zum Kernel ein "Endlossjump" gemacht also

stop:
jmp stop

Funktioniert doch auch, oder?
In diesem Fall nicht, weil du ja nie dahinkommst. Du springst mit jmp 0x08:0x10000 zum Kernel, aber der Kernel weiß nicht, wie er zurückkommt. Du könntest mit call statt jmp zum Kernel springen, dann funktioniert das.

Zitat
Da muss ein -T vor das link.ld.

Wenn ich das mache, bekomme ich folgende Fehlermeldung:

ld: cannot perform PE operations on non PE out put file 'kernel.bin'.
Ohne -T sieht der ld das Linker-Skript nicht als das primäre Linkerskript an und erzeugt eine .exe-Datei. (Davon kannst du dich mittels objdump -p kernel.bin überzeugen.)

Es gibt zwei Möglichkeiten, um doch eine Binärdatei zu bekommen: Entweder nimmst du einen Cross Compiler (z.B. einen (http://lowlevel.brainsware.org/wiki/index.php/Crosscompiler_f%C3%BCr_Windows), den ich erstellt habe, oder machst dir einen selbst (http://lowlevel.brainsware.org/wiki/index.php/Cross-Compiler)) oder du baust deinen Build-Prozess um: Aus link.ld entfernst du die Zeile OUTPUT_FORMAT("binary") und rufst nach dem Linken noch objcopy auf um die Datei ins Binärformat zu wandeln: objcopy -O binary kernel.bin
Titel: Re: C - Kernel wird nicht geladen
Beitrag von: Pk3 am 19. August 2009, 20:03
So, habe jetzt alles verbessert. Jedoch passiert wieder nichts :(.
Liegt das vielleicht an der Addresse dess Kernels? Der Kernel is im moment
auf 0x1000 und aufrufen tu ich ihn mit jmp 08h:01000h , eine Endlosschleife
ist auch am Ende dess Kernels.

Ich versteh nicht warum das nicht geht.... :(.
Titel: Re: C - Kernel wird nicht geladen
Beitrag von: Jidder am 19. August 2009, 20:15
Warum hast du ihn jetzt an diese Adresse gelegt?
Titel: Re: C - Kernel wird nicht geladen
Beitrag von: Pk3 am 19. August 2009, 21:05
Wenn ich ihn an eine Addresse tu, die größer als 0x10000 ist, dann meldet mir nasm.exe das die Addresse zu groß ist.

Achja, das objcopy funktioniert bei mir nicht. Da kommt immer eine
Meldung, in der steht, das das Dateiformat *.bin nicht bekannt ist.
Titel: Re: C - Kernel wird nicht geladen
Beitrag von: Jidder am 19. August 2009, 21:14
Also das Zusammenfassen von Fehlermeldungen ist immer so eine Sache ...

Wo gibt dir NASM die Fehlermeldung? Was sagt der genau? Was ist die genaue Fehlermeldung von objcopy?
Titel: Re: C - Kernel wird nicht geladen
Beitrag von: Pk3 am 19. August 2009, 21:15
Das gebe ich ein:
objcopy -O binary kernel.bin

Und das kommt:
objcopy:kernel.bin: File format not recognized
Titel: Re: C - Kernel wird nicht geladen
Beitrag von: Jidder am 19. August 2009, 21:24
Kommt die Meldung immer? Auch wenn du vorher kernel.bin löschst, und sie mit ld erneut erstellst?
Titel: Re: C - Kernel wird nicht geladen
Beitrag von: Pk3 am 19. August 2009, 21:31
Die Meldung kommt immer, oder kann das sein das ich eine alte Version
von objcopy.exe habe? Wenn ja, kannst du mir bitte einen Downloadlink
schicken wo man die neue findet? Ich hab bei Google lange gesucht
bis ich die gefunden habe.

Hier die Batch - Datei:

ECHO OFF
nasmw -f bin -o boot.bin boot.asm

D:\Programme\CodeBlocks\MinGW\Bin\gcc -ffreestanding -c -o kernel.o kernel.c

D:\Programme\CodeBlocks\MinGW\Bin\ld -T link.ld -o kernel.bin

objcopy -O binary kernel.bin

copy /b boot.bin + kernel.bin os.img

pause

rawwritewin.exe C:\Users\Pk3\Desktop\C_Kernel\os.img a:


Edit:
objcopy.exe ist bei mir 676kb groß.
Titel: Re: C - Kernel wird nicht geladen
Beitrag von: Jidder am 19. August 2009, 22:29
In diesem Fall ist sowohl Eingabe wie Ausgabe. Wenn du objcopy -O binary kernel.bin kernel-output.bin schreibst, dann ist kernel-output.bin die Ausgabe.

Ich kann mir nicht erklären, warum das so nicht funktioniert.
Titel: Re: C - Kernel wird nicht geladen
Beitrag von: Pk3 am 19. August 2009, 22:40
Versteh ich auch nicht.... wie gesagt, vielleicht liegt das an der Version von objcopy.exe. Bei mir ist die 676kb groß. Das Linke - Script sieht jetzt so aus:

INPUT("kernel.o")
ENTRY(_begin)
SECTIONS
{
  .text  0x1000 :
  {
    *(.text)
  }
  .data  :
  {
    *(.data)
  }
  .bss  :
  {
    *(.bss)
  }
}
Titel: Re: C - Kernel wird nicht geladen
Beitrag von: Pk3 am 19. August 2009, 22:47
objcopy -O binary --input-target binary kernel.bin kernel-output.bin

Mit --input-target binary funktionierts ohne Meldung.
Aber so ist es doch sinnlos, weiß jemand wie der richtige
input-target heißt?
Titel: Re: C - Kernel wird nicht geladen
Beitrag von: Jidder am 19. August 2009, 22:52
Die Version kannst du mit objcopy -V feststellen.

Das Problem an MinGW ist, dass es halt stark auf Windows spezialisiert ist. Eventuell solltest du wie ich bereits oben vorgeschlagen habe auf einen Cross Compiler umsteigen.
Titel: Re: C - Kernel wird nicht geladen
Beitrag von: Pk3 am 19. August 2009, 23:23
Habe mir jetzt einen CrossCompiler heruntergeladen und es damit probiert.
Das objcopy geht jetzt endlich :). Die größe der IMG Datei hat sich auch verändert (von 5kb auf 1kb).

Und wenn ich das Image auf eine Diskette schreibe, und darauf boote, dann
rebootet sich der PC von alleine, ohne das ich irgentwas mache.

Ich weiß nicht wo der Fehler liegt.... hab schon so viel rumprobiert
und nichts klappt....   :-(.
Titel: Re: C - Kernel wird nicht geladen
Beitrag von: Jidder am 19. August 2009, 23:37
Hi,

für den Anfang solltest du zum Testen Bochs oder Qemu benutzen. Die können dir meistens auch Hinweise geben, was schief gelaufen ist.

Zum Beispiel erstellt Bochs ein Log, in dem die Instruktion bei der das Problem aufgetreten ist, sowie der Zustand der CPU (Register, etc.) stehen.

Ich benutze meistens diese Konfigurationsdatei für Bochs:
floppya: 1_44="os.img", status=inserted
boot: floppy

romimage: file=$BXSHARE/BIOS-bochs-latest, address=0xe0000
cpu: count=1, ips=10000000, reset_on_triple_fault=1
megs: 8

vgaromimage: file=$BXSHARE/VGABIOS-lgpl-latest
vga: extension=vbe

log: bochs.log
logprefix: %t-%e-@%i-%d

In einer Datei namens bochs.bxrc oder so speichern, und in das Verzeichnis mit deinem os.img kopieren und dann per Doppelklick starten.
Titel: Re: C - Kernel wird nicht geladen
Beitrag von: Pk3 am 20. August 2009, 10:04
Danke für den Tipp, hab das jetzt mal gemacht und folgende Log-Datei
bekommen.

http://xyross.de/bochs.log

Darin fällt mir nur auf, das der Protect-Mode eingeschaltet wurde (Zeile 756)

00065895575-i-@006f0018-[CPU0 ] protected mode
und das er beendet

00065895575-e-@006f0018-[CPU0 ] exception(): 3rd (13) exception with no resolution, shutdown status is 00h, resetting
nachdem

00065895575-i-@006f0018-[CPU0 ] >> add dword ptr ds:[eax], eax : 0100
ausgeführt wurde. Also muss da der Fehler sein.
Jedoch finde ich im Assembler-Code (boot.asm) kein
"add", aber den Register "eax". Die 0100 ähnelt der Addresse
dess Kernels, fehlt halt eine Null, die habe ich anschließend rangehängt
also beim jmp, jetzt siehts so aus:

jmp 08h:010000h
Dann habe ich das ganze nochmal gemacht und jetzt sagt Bochs das:

00002609039-i-@00010006-[CPU0 ] >> and byte ptr gs:[edi+ebp*2+0x20], dh : 6520746F20
00002609039-e-@00010006-[CPU0 ] exception(): 3rd (13) exception with no resolution, shutdown status is 00h, resetting

(Hier die Log-Datei: http://xyross.de/bochs2.log)


Da weiß ich nicht was ich machen soll, damits funktioniert.
Es passiert aber aufjedenfall nach dem Jump zum Kernel.

Edit:

Ich habe den Fehler gefunden, er liegt im C - Code:

char *Text = "Welcome to Protected Mode";
char *VideoMem = (char*)0xB8000;

while(*Text) 
{
*VideoMem = *Text; 
*VideoMem++; 
*VideoMem = 7; 
*VideoMem++; 
*Text++; 
}

Ich habe mal alles aus der begin() - Funtkion raus, auser die
Endlosschleife ( for(;;); ), jetzt sagt Bochs folgendes:

00141710000-i-@00010004-[CPU0 ] >> jmp .+0xfffffffe (0x00010004) : EBFE
Hab dann mal bei Google nach einer printf - Funktion gesucht und diese
verwendet:

void printf(char *text)
{
  char *ptr;
 
  for ( ptr = (char *)0xB8000; *text != 0; text++ )
  {
    *(ptr++) = *text;
    *(ptr++) = 0xe;
  }
}

int begin()
{
printf("Test");

for(;;);
}

als Fehler bekomme ich:
00026099052-i-@00000008-[CPU0 ] >> (invalid)  : FFFF
Titel: Re: C - Kernel wird nicht geladen
Beitrag von: Jidder am 20. August 2009, 11:48
Hi,

00065895575-i-@006f0018-[CPU0 ] >> add dword ptr ds:[eax], eax : 0100
ausgeführt wurde. Also muss da der Fehler sein.
Jedoch finde ich im Assembler-Code (boot.asm) kein
"add", aber den Register "eax".
Wenn du den Code nicht als deinen erkennst, dann heißt das, dass dein Bootloader/Kernel irgendwo ins Nirvana springt, oder dass sich dein Kernel nicht an der Stelle befindet, wo der Bootloader hinspringt. Ich vermute letzteres.

Zitat
Die 0100 ähnelt der Addresse
dess Kernels, fehlt halt eine Null, die habe ich anschließend rangehängt
also beim jmp, jetzt siehts so aus:
Hinter dem Assemblerbefehl steht immer der Maschinencode in Hexadezimaldarstellung. Die Ähnlichkeit mit irgendwelchen Adressen hat an dieser Stelle nichts zu bedeuten. Wenn dein Programmfluss irgendwo im Nirvana landet, dann ist dieser Speicher einfach mit zufälligen Werten, je nach Art des Speichers auch mit Nullen (0x00) oder Einsen (0xFF) gefüllt.

Das Interessante hier ist nicht der Befehl selbst, sondern der Zustand der CPU. Der Wert des Befehlszählers (RIP bzw. EIP) ist 00000000006f0018, was weit ab von deinem Programm ist.

Zitat
00002609039-i-@00010006-[CPU0 ] >> and byte ptr gs:[edi+ebp*2+0x20], dh : 6520746F20
00002609039-e-@00010006-[CPU0 ] exception(): 3rd (13) exception with no resolution, shutdown status is 00h, resetting
Dies mal ist der Maschinencode wesentlich interessanter. 6520746F20 sieht aus wie ASCII Code und zwar entspricht der genau dem "e to " aus deinem "Welcome to Protected Mode". Das heißt die CPU versucht die Daten auszuführen, weil die Daten in deiner Binärdatei vor dem Code liegen.

Als du die Ausgabe entfernt hast, hast du auch diesen String aus deinem Programm entfernt. Dann war der Datenbereich deines Programms leer und wieder der Code das erste in deinem Progamm. Das Fehler liegt also in dem Prozess, wie du den Kernel erstellst, nicht am Code des Kernels.

Der String landet in der *(.rodata) oder *(.rdata) Sektion je nach Compiler. Änder mal dein Linkerskript so, dass du die Sektionen erwähnst:
INPUT("kernel.o")
ENTRY(_begin)
SECTIONS
{
  .text  0x10000 :
  {
    *(.text)
    *(.rdata)
    *(.rodata)
  }
  .data  :
  {
    *(.data)
  }
  .bss  :
  {
    *(.bss)
  }
}

Außerdem würde ich dir mal empfehlen, dich mehr mit den Werkzeugen auseinander zu setzen. objdump kann dir viele Informationen über deine Objekt-Dateien (und über deinen Kernel solange er nicht eine Binärdatei ist) liefern, mit ndisasm, welches bei NASM dabei ist, kannst du den Kernel, wenn er eine flache Binärdatei ist, disassemblieren. Außerdem könntest du dich mal mit dem Debugger von Bochs auseinander setzen. Mit lb 0x7c00 kannst du da einen Breakpoint an den Anfang des Bootloaders setzen, mit c kommst du dann bis zu diesem Breakpoint, mit s kannst du single steppen und mit n kannst du einen step over (z.B. über BIOS Interrupts) machen.

All diese Programme haben außerdem Handbücher, die online verfügbar sind.
Titel: Re: C - Kernel wird nicht geladen
Beitrag von: Pk3 am 20. August 2009, 12:51
Ich habs jetzt, der Fehler war im C Code, ich habe das ausprobiert:

int begin() {
char *vidmem = (char *) 0xB8000;
unsigned int i=0;
while(i < (80*25*2)) {
vidmem[i]='G';
i++;
vidmem[i]=0x06;
i++;
};

for(;;);
}

Da wird der Bildschirm mit "G" gefüllt.
Aber wenn ich eine Funktion aufrufen will, in dem man ein
char übergeben muss, wird die Funktion net ausgeführt.
z.B.:

void printf(char *text);

int begin() {
printf("TEST");
while(1);
}

void printf(char *text) {
   char *vidmem = (char *) 0xB8000;
   unsigned int i=0;
   while(i < (80*25*2))
   {
      vidmem[i]='G';
      i++;
      vidmem[i]=0x06;
      i++;
   };
};
Titel: Re: C - Kernel wird nicht geladen
Beitrag von: MNemo am 20. August 2009, 13:24
Aber wenn ich eine Funktion aufrufen will, in dem man ein
char übergeben muss, wird die Funktion net ausgeführt.
z.B.:

void printf(char *text);

int begin() {
printf("TEST");
while(1);
}
Hast du den Code genau so ausprobiert? In dem Fall sollte gcc keine Optimierung vornehmen.  Ansonsten optimiert gcc an so nem printf scheinbar manchmal. Siehe dazu das Zitat aus einem anderen Thread:

Der GCC optimiert ein printf("foo\n") zu einem puts("foo"), weil ein standardkonformes puts automatisch ein \n ausgibt.

Ich schätze da gibts es mindestens folgende Möglichkeiten:
- printf nicht printf nennen
- oder standardkonformes puts implementieren
- oder angeblich soll da -fno-builtin oder -fno-builtin-printf helfen.

-> http://www.ciselant.de/projects/gcc_printf/gcc_printf.html
Titel: Re: C - Kernel wird nicht geladen
Beitrag von: Pk3 am 20. August 2009, 13:26
Hmm..... ich kann nur char´s übergeben, die net mehr als 2 Zeichen enthalten,
also z.B. printf("hi"); , das geht, aber printf("hih"); geht nicht.
Titel: Re: C - Kernel wird nicht geladen
Beitrag von: Pk3 am 20. August 2009, 13:28
@MNemo

Ich habe die Funktion auch schon unbenannt in "v_print", hilft aber auch nix  :-(.

void v_print(char *msg);

int begin() {
v_print("Die");

while(1);
}

void v_print(char *msg) {
char *vidmem = (char *) 0xB8000;
unsigned int i=0;
unsigned int s=0;
while(s < sizeof(msg) - 1) {
vidmem[i]=msg[s];
i++;
vidmem[i]=0x06;
i++;
s++;
}
}
Titel: Re: C - Kernel wird nicht geladen
Beitrag von: MNemo am 20. August 2009, 13:44
void v_print(char *msg) {
char *vidmem = (char *) 0xB8000;
unsigned int i=0;
unsigned int s=0;
while(s < sizeof(msg) - 1) {
vidmem[i]=msg[s];
i++;
vidmem[i]=0x06;
i++;
s++;
}
}
Emm… Ja…

Deine C Kenntnisse sind ja nicht gerade berauschend.
sizeof(msg) wird dir immer 4(bzw. bei 64-Bit CPUs 8 ) liefern. weil msg nur mal ein Pointer ist. und die sind 4 bzw. 8 Byte groß.

du solltest dir bei der String Ausgabe eher von nutzen machen, dass c-strings ein Null-Byte am ende haben.

BTW: ein char ist _ein_ Zeichen. ein string ist ein array aus chars mit einem 0-Byte(char) am ende
Titel: Re: C - Kernel wird nicht geladen
Beitrag von: Pk3 am 20. August 2009, 13:56
Das Problem liegt da woanders, wie gesagt, wenn ich an eine Funktion ein Char-Array übergebe und deren inhalt länger als 2 Zeichen ist dann wird die Funktion nichmal aufgerufen.
Titel: Re: C - Kernel wird nicht geladen
Beitrag von: MNemo am 20. August 2009, 14:02
was sagt den
$ objdump -d kernel.odazu?
Titel: Re: C - Kernel wird nicht geladen
Beitrag von: Cjreek am 20. August 2009, 14:04
Hi,

versuch doch mal folgendes:

void v_print(char *msg) {
  char *vidmem = (char *) 0xB8000;
  int i = 0;
  int j = 0;
  while ((byte)msg[i] != 0)
  {
     vidmem[j] = msg[i];
     j++;
     vidmem[j] = (char)0x07
     j++;
     i++;
  }
}

Für Syntaxfehler übernehme ich keine Haftung. Bin kein C-ler  :-D
Titel: Re: C - Kernel wird nicht geladen
Beitrag von: Pk3 am 20. August 2009, 14:05
file format pe-i386
Disassembly of section .text:

00000000 <.text>:
   0:   44              inc    %esp
   1:   65 72 00        jb     4 <_begin>

00000004 <_begin>:
   4:   55              push   %ebp
   5:   89 e5           mov    %esp,%ebp
   7:   68 00 00 00 00  push   $0x0
   c:   e8 13 00 00 00  call   24 <_v_print>
  11:   83 c4 04        add    $0x4,%esp
  14:   eb 02           jmp    18 <_begin+0x14>
  16:   eb 08           jmp    20 <_begin+0x1c>
  18:   eb fa           jmp    14 <_begin+0x10>
  1a:   8d b6 00 00 00  lea    0x0(%esi),%esi
  1f:   00
  20:   89 ec           mov    %ebp,%esp
  22:   5d              pop    %ebp
  23:   c3              ret

00000024 <_v_print>:
  24:   55              push   %ebp
  25:   89 e5           mov    %esp,%ebp
  27:   83 ec 10        sub    $0x10,%esp
  2a:   c7 45 fc 00 80  movl   $0xb8000,0xfffffffc(%ebp)
  2f:   0b 00
  31:   c7 45 f8 00 00  movl   $0x0,0xfffffff8(%ebp)
  36:   00 00
  38:   c7 45 f4 00 00  movl   $0x0,0xfffffff4(%ebp)
  3d:   00 00
  3f:   90              nop
  40:   8b 45 08        mov    0x8(%ebp),%eax
  43:   8b 55 f4        mov    0xfffffff4(%ebp),%edx
  46:   01 d0           add    %edx,%eax
  48:   80 38 00        cmpb   $0x0,(%eax)
  4b:   75 03           jne    50 <_v_print+0x2c>
  4d:   eb 31           jmp    80 <_v_print+0x5c>
  4f:   90              nop
  50:   8b 45 fc        mov    0xfffffffc(%ebp),%eax
  53:   8b 55 f8        mov    0xfffffff8(%ebp),%edx
  56:   01 d0           add    %edx,%eax
  58:   8b 55 08        mov    0x8(%ebp),%edx
  5b:   8b 4d f4        mov    0xfffffff4(%ebp),%ecx
  5e:   01 ca           add    %ecx,%edx
  60:   8a 0a           mov    (%edx),%cl
  62:   88 08           mov    %cl,(%eax)
  64:   ff 45 f8        incl   0xfffffff8(%ebp)
  67:   8b 45 fc        mov    0xfffffffc(%ebp),%eax
  6a:   8b 55 f8        mov    0xfffffff8(%ebp),%edx
  6d:   01 d0           add    %edx,%eax
  6f:   c6 00 06        movb   $0x6,(%eax)
  72:   ff 45 f8        incl   0xfffffff8(%ebp)
  75:   ff 45 f4        incl   0xfffffff4(%ebp)
  78:   eb c6           jmp    40 <_v_print+0x1c>
  7a:   8d b6 00 00 00  lea    0x0(%esi),%esi
  7f:   00
  80:   89 ec           mov    %ebp,%esp
  82:   5d              pop    %ebp
  83:   c3              ret

00000084 <_v_clear>:
  84:   55              push   %ebp
  85:   89 e5           mov    %esp,%ebp
  87:   83 ec 10        sub    $0x10,%esp
  8a:   c7 45 fc 00 80  movl   $0xb8000,0xfffffffc(%ebp)
  8f:   0b 00
  91:   c7 45 f8 00 00  movl   $0x0,0xfffffff8(%ebp)
  96:   00 00
  98:   81 7d f8 9f 0f  cmpl   $0xf9f,0xfffffff8(%ebp)
  9d:   00 00
  9f:   76 02           jbe    a3 <_v_clear+0x1f>
  a1:   eb 1e           jmp    c1 <_v_clear+0x3d>
  a3:   8b 45 fc        mov    0xfffffffc(%ebp),%eax
  a6:   8b 55 f8        mov    0xfffffff8(%ebp),%edx
  a9:   01 d0           add    %edx,%eax
  ab:   c6 00 20        movb   $0x20,(%eax)
  ae:   ff 45 f8        incl   0xfffffff8(%ebp)
  b1:   8b 45 fc        mov    0xfffffffc(%ebp),%eax
  b4:   8b 55 f8        mov    0xfffffff8(%ebp),%edx
  b7:   01 d0           add    %edx,%eax
  b9:   c6 00 07        movb   $0x7,(%eax)
  bc:   ff 45 f8        incl   0xfffffff8(%ebp)
  bf:   eb d7           jmp    98 <_v_clear+0x14>
  c1:   89 ec           mov    %ebp,%esp
  c3:   5d              pop    %ebp
  c4:   c3              ret
Titel: Re: C - Kernel wird nicht geladen
Beitrag von: MNemo am 20. August 2009, 14:14
Zitat
c:   e8 13 00 00 00  call   24 <_v_print>
also der Aufruf findet eindeutig statt.

ändere mal diese Zeile in deinem linkscript
    *(.rodata)
zu
    *(.rodata*)
gcc steckt strings AFAIK in sections mit namen wie
 .rodata-str-XY
vielleicht ist dein string ja einfach nicht mit gelinkt.
Titel: Re: C - Kernel wird nicht geladen
Beitrag von: Pk3 am 20. August 2009, 14:33
Jetzt kann ich maximal ne 3-Zeichen-Char-Array an eine Funktion übergeben  :-D. Mehr geht nich....

Link.ld

INPUT("C:\Users\Pk3\Desktop\C_Kernel\kernel.o")
ENTRY(_begin)
SECTIONS
{
  .text  0x10000 :
  {
    *(.text)
    *(.rdata)
    *(.rodata*)
  }
  .data  :
  {
    *(.data)
  }
  .bss  :
  {
    *(.bss)
  }
}

kernel.c
void v_print(char *msg);
void v_clear();

int begin() {
v_print("Derd");
while(1);
}

void v_print(char *msg) {
char *vidmem = (char *) 0xB8000;
unsigned int i=0;
unsigned int s=0;
while(msg[s] != 0) {
vidmem[i]=msg[s];
i++;
vidmem[i]=0x06;
i++;
s++;
}
}

void v_clear() {
char *vidmem = (char *) 0xb8000;
unsigned int i=0;
while(i < (80*25*2)) {
vidmem[i]=' ';
i++;
vidmem[i]=0x07;
i++;
}
}

boot.asm
[BITS 16]
org 0x7c00

%define STACKSEGMENT  0x9000 ; lineare Adresse des Stacks  : 0x90000
%define STACKSIZE     0x200 ; Größe des Stacks     : 512Byte
%define KERNELSEGMENT 0x1000 ; lineare Adresse des Kernels : 0x10000

jmp START
 
GDTR:
limit  dw (GDT_END - GDT - 1)
base   dd (0)
GDT:
NULL_DESCRIPTOR EQU $-GDT

dd 0
dd 0
CODE_DESCRIPTOR EQU $-GDT
dw 0ffffh
dw 0
db 0
db 09ah
db 0cfh
db 0
DATA_DESCRIPTOR EQU $-GDT
dw 0ffffh
dw 0
db 0
db 092h
db 0cfh
db 0
GDT_END:

START:
cli ; keine Interrupts
mov ax, STACKSEGMENT
mov ss, ax ; Stacksegment setzen
mov sp, STACKSIZE ; Größe des Stacks festlegen
xor ax, ax ; ax = 0
mov ds, ax ; Datensegment auf 0 setzen
sti

xor bx, bx ; Ziel-Offset : 0x0
mov ax, KERNELSEGMENT ; Ziel-Segment : 0x1000
mov es, ax
mov ah, 0x2 ; Funktion 0x2 : Sektor lesen
mov al, 1 ; Anzahl der Sektoren : 1
mov ch, 0 ; Track        : 0
mov cl, 2 ; LSN : 2
mov dh, 0 ; Head : 0
mov dl, 0 ; Laufwerk     : A
int 0x13 ; Interrupt    : 0x13

cli ; keine Interrupts
mov ax, cs ; Code-Segment holen
mov ds, ax ; Daten-Segment gleichsetzen
xor eax, eax ; ax = 0
mov es, ax ; Extra-Segment auf Null setzen
 
mov si, GDT ; Quelle : GDT
xor di, di ; Ziel : 0x0000
mov cx, 6 ; 6 DoubleWords kopieren (ganze GDT)
rep movsd

lgdt [GDTR]
 
mov eax, cr0
or eax, 1 ; Bit0 setzen (PE-Bit enabled)
mov cr0, eax

db 0xea ; FAR-JUMP zum Codesegment
dw (PMODE)
dw 0x8

[BITS 32] ; 32 Bit-Code erstellen
PMODE:
xor      eax, eax
mov      eax, 2 ; Selektor für das Datensegment erstellen
shl      eax, 3
 
mov ds, ax ; Daten-, Stack- und Extrasegment mit
mov ss, ax ; Datensegmentdeskriptor laden
mov es, ax
xor ax, ax
mov fs, ax ; fs und gs mit Nulldeskriptor laden
mov gs, ax
mov esp, 09000h ; Stack setzen

jmp 08h:010000h

times 512-($-$$)-2 db 0
dw 0x0AA55
Titel: Re: C - Kernel wird nicht geladen
Beitrag von: DerHartmut am 20. August 2009, 15:05
Mach aus dem char* vidmem mal bitte ein unsigned long *vidmem = (unsigned long *)0xB8000
Titel: Re: C - Kernel wird nicht geladen
Beitrag von: MNemo am 20. August 2009, 15:08
Dein code tut bei mir ohne Probleme.

$ nasm -f bin boot.asm
$ gcc -m32 -ffreestanding -fleading-underscore -c kernel.c
$ ld -melf_i386 -T link.ld -o kernel.bin kernel.o
$ dd if=/dev/zero of=floppy.img bs=512 count=2880
$ cat boot kernel.bin | dd of=floppy.img conv=notrunc
$ qemu -fda floppy.img

Ich spare mir das objcopy mit
OUTPUT_FORMAT( "binary" ) im linkerscript

@hartmut: warum denn das?
[edit]ich kann mir nicht vorstellen das es tut wenn man alle 4 bzw. 8 byte abwechselnd ein Daten- und Attribut-Byte in den RAM schreibt.[/edit]
Titel: Re: C - Kernel wird nicht geladen
Beitrag von: DerHartmut am 20. August 2009, 15:09
Weil ich es so gemacht habe *G*
Titel: Re: C - Kernel wird nicht geladen
Beitrag von: Pk3 am 20. August 2009, 16:06
@MNemo

-m32 -fleading-underscore
So funktionierts, jetzt geht alles, danke an alle  :-D!