Autor Thema: A beginner's problem:outsourching a function in a c kernel produces wrong result  (Gelesen 4989 mal)

flyingdd

  • Beiträge: 3
    • Profil anzeigen
Gespeichert
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.

MNemo

  • Beiträge: 547
    • Profil anzeigen
Gespeichert
2kernel.c commpiliert bei mir erst gar nicht.

Zitat von: gcc -m32 -o 2kernel.o -c 2kernel.c -nostdlib -nostartfiles -nodefaultlibs
2kernel.c: In function ‘printstring’:
2kernel.c:10:41: warning: assignment makes integer from pointer without a cast
2kernel.c: In function ‘printnr’:
2kernel.c:34:11: error: incompatible types when assigning to type ‘char[10]’ from type ‘int’
2kernel.c:40:16: warning: assignment makes pointer from integer without a cast


Code: (Zeile 8-10) [Auswählen]
  for (i = 0; string != '\0' && i<80 * (25-line); i++) {
        // Zeichen i in den Videospeicher kopieren
        videoram[i * 2 + 80 * 2 * line] = string;
string ist vom typ char*, also ein pointer. du willst hier wohl eher string[ i ] stehen haben.

Code: (Zeile 34) [Auswählen]
buf = (nr2%10)+48;
buf ist vom typ char[] auch hier soll es wohl eher buf[ i ] heißen

Code: (Zeile 40) [Auswählen]
videoram = buf[length - i/2];
und hier wieder das selbe

Und dann läuft das bei mir. Er gibt zumindest die $((33+55)) korrekt aus
„Wichtig ist nicht, besser zu sein als alle anderen. Wichtig ist, besser zu sein als du gestern warst!“

DerHartmut

  • Beiträge: 236
    • Profil anzeigen
    • Mein Blog
Gespeichert
Kurze Anmerkung: Bitte nutze einen Paste-Service wie pastebin.com, um dort größere Mengen Code abzulegen und für andere komfortabel zur Verfügung zu stellen.
$_="krJhruaesrltre c a cnp,ohet";$_.=$1,print$2while s/(..)(.)//;
Nutze die Macht, nutze Perl ;-)

flyingdd

  • Beiträge: 3
    • Profil anzeigen
Gespeichert
Kurze Anmerkung: Bitte nutze einen Paste-Service wie pastebin.com, um dort größere Mengen Code abzulegen und für andere komfortabel zur Verfügung zu stellen.
geht klar! wusste ich nur nicht, sory

flyingdd

  • Beiträge: 3
    • Profil anzeigen
Gespeichert
2kernel.c commpiliert bei mir erst gar nicht.

Zitat von: gcc -m32 -o 2kernel.o -c 2kernel.c -nostdlib -nostartfiles -nodefaultlibs
2kernel.c: In function ‘printstring’:
2kernel.c:10:41: warning: assignment makes integer from pointer without a cast
2kernel.c: In function ‘printnr’:
2kernel.c:34:11: error: incompatible types when assigning to type ‘char[10]’ from type ‘int’
2kernel.c:40:16: warning: assignment makes pointer from integer without a cast


Code: (Zeile 8-10) [Auswählen]
  for (i = 0; string != '\0' && i<80 * (25-line); i++) {
        // Zeichen i in den Videospeicher kopieren
        videoram[i * 2 + 80 * 2 * line] = string;
string ist vom typ char*, also ein pointer. du willst hier wohl eher string[ i ] stehen haben.

Code: (Zeile 34) [Auswählen]
buf = (nr2%10)+48;
buf ist vom typ char[] auch hier soll es wohl eher buf[ i ] heißen

Code: (Zeile 40) [Auswählen]
videoram = buf[length - i/2];
und hier wieder das selbe

Und dann läuft das bei mir. Er gibt zumindest die $((33+55)) korrekt aus


Das ist seltsam. Muss wohl beim Copy und Paste passiert sein, denn ich habe eigentlich alles so, wie Du es gesagt hast, nur ich habe es falsch gepostet irgendwie.

 

Einloggen