Programm für PrettyOS schreiben - Einsprungpunkt? makefile? .ld?



  • Hallo,
    ich hab mal versucht, ein Programm für PrettyOS zu kompilieren und auszuführen. Ich bekomme einen PageFault. Ich habe den selben Code wie für die Hello.elf benutzt.
    Ich vermute, das irgendwas mit dem Einsprungpunkt falsch ist.
    Mein ld-file (vermutlich falsch, ich weiß nur nicht was):

    ENTRY(_start)
    OUTPUT_FORMAT(elf32-i386)
    OUTPUT_ARCH(i386)
    SECTIONS
    {
        . = 0x1400000;
        .text   : { __code_start = .;   *(.text*)         }
        .data   : { __data_start = .;   *(.data)          }    
        .rodata : { __rodata_start = .; *(.rodata)        }
        .bss    : { __bss_start = .;    *(.bss) *(COMMON) }
         __end = .; 	
    }
    

    mein makefile (vermutlich richtig)

    main: test.c userlib.c userlib.h
    	i586-elf-gcc -c userlib.c -std=c99 -march=i386 -mtune=i386 -m32 -fno-pic -Werror -Wall -O -ffreestanding -fleading-underscore -nostdlib -nostdinc -fno-builtin -fno-stack-protector -Iinclude
    	i586-elf-gcc -c test.c -std=c99 -march=i386 -mtune=i386 -m32 -fno-pic -Werror -Wall -O -ffreestanding -fleading-underscore -nostdlib -nostdinc -fno-builtin -fno-stack-protector -Iinclude
    	i586-elf-ld *.o -T user.ld -Map user.map -nostdinc -o test.elf
    

    Ich hätte es ja gerne so gemacht, wie für die Hello.elf, leider hab ich nirgends die entsprechenden Dateien gefunden...

    Was mache ich falsch?

    mfg
    Mr. X


  • Mod

    Oh sorry, ich habe der Einfachheit einfach program.c gegen hello.c ausgetauscht un dan dessen Stelle kompiliert. Daher gelten die gleichen Bedingungen wie für program.c:

    Das Assembler-Programm start.asm muss mitgelinkt werden:

    ; start.asm
    
    [BITS 32]
    extern __bss_start
    extern __end
    extern _main
    global _start
    
    _start:
        mov esp, 0x600000 ; stackpointer
        call _main
    
        jmp $
    

    Das Linker-Skript user.ld:

    ENTRY(_start)
    OUTPUT_FORMAT(elf32-i386)
    OUTPUT_ARCH(i386)
    SECTIONS
    {
        . = 0x1400000;
        .text   : { __code_start = .;   *(.text*)         }
        .data   : { __data_start = .;   *(.data)          }    
        .rodata : { __rodata_start = .; *(.rodata)        }
        .bss    : { __bss_start = .;    *(.bss) *(COMMON) }
         __end = .; 	
    }
    

    Im makefile findet sich:

    ... 
            $(wildcard $(USERDIR)/*)
    	rm -f *.o 
    	$(NASM) -O32 -f elf $(USERDIR)/start.asm -I$(USERDIR)/ -o start.o
    	$(CC) $(USERDIR)/*.c -c -I$(USERDIR) -m32 -fno-pic -Werror -Wall -O -ffreestanding -fleading-underscore -nostdlib -nostdinc -fno-builtin
    	$(NASM) -O32 -f elf $(USERDIR)/start.asm -o start.o
    	$(LD) *.o -T $(USERDIR)/user.ld -Map $(USERDIR)/kernel.map -nostdinc -o $(USERDIR)/program.elf
    	rm -f *.o
    

    Am besten nennen wir das Verzeichnis zum Testen von neuen Programmen USERTESTDIR anstelle USERDIR.

    Also einfach start.o für den korrekten Einsprung dazu linken. 🙂



  • Danke, es funktioniert.

    Übrigens, ich habe einen Bug gefunden:
    Die Ausgabe eines Programms, z.B. Hello.elf hat folgenden Fehler:
    Das erste Zeichen ist nach unten verrutscht, sodass dort steht:

    ello, Pretty...
    This piece of...
    
    $>
    H
    

    Zudem ist das laden eines Programms von der Floppy sehr langsam und PrettyOS sucht sehr lange, falsch man einen falschen Namen angegeben hat. Zudem sucht er, selbst wenn nichts eingegeben wurde.

    Verwendetes System: Virtual Box. PrettyOS Revision 80

    mfg
    Mr. X


  • Mod

    Danke für die Hinweise! Das Laden von Floppy ist bisher leider alles andere als perfekt, aber es läuft. An der Optimierung wird gerade gearbeitet.

    EDIT: Ab Revision 81 wird die Leereingabe abgefangen. Der delay von 50 Millisekunden bei Lese-/Schreibvorgängen wurde entfernt.

    Kannst Du bitte deine Konfiguration im Unterverzeichnis bei hello.c (o.ä.) und dein funktionierendes makefile für andere hier bitte posten?



  • Das makefile ist nicht repräsentativ. Es ist nicht so kryptisch, wie Euers 😉
    Ich hab einfach ein einfaches makefile in einem neuen Verzeichnis angelegt und make.exe und nasmw.exe dahin kopiert.


  • Mod

    Zeigst Du uns dein Programm? 🙂

    Vor allem: wie ist es gelaufen? Hat es geklappt?


  • Mod

    Das makefile ist nicht repräsentativ. Es ist nicht so kryptisch, wie Euers 😉 Ich hab einfach ein einfaches makefile in einem neuen Verzeichnis angelegt und make.exe und nasmw.exe dahin kopiert.

    Gerade deshalb ist es für Einsteiger sicher interessant.


  • Mod

    Übrigens, ich habe einen Bug gefunden:
    Die Ausgabe eines Programms, z.B. Hello.elf hat folgenden Fehler:
    Das erste Zeichen ist nach unten verrutscht, sodass dort steht:
    Code:
    ello, Pretty...
    This piece of...

    $>
    H

    Ursache aufgespürt:
    Nach Reduktion der Systemfrequenz (in timer.c) von 1000 Hz (versuchsweise wie bei Linux) auf 100 Hz läuft die Bildschirmausgabe wieder geordnet. Dies zeigt, dass man die Taskwechsel-Freqenz - ohne Lock der kritischen Abschnitte zwischen den Tasks/Threads - nicht beliebig hoch drehen sollte. Momentan ist das Scheduling noch fest an diese Frequenz gekoppelt.

    Rev.82: http://www.henkessoft.de/OS_Dev/Bilder/Rev82.PNG



  • PrettyOS funktioniert bei mir seit Revision 82 oder 81 nicht mehr. Es stürzt nach 1 sek. ab. Der Zug bleibt stehen, die Laufzeitangabe auch. Es nimmt keine Tastatureingaben an. (Eingabezeile ist aber schon da)
    Änderungen an der konfiguration der Virtuellen Maschine haben keine Verbesserungen gebracht.

    Nun aber zum eigentlichen Thema:
    Ordner für mein Programm:

    userlib.h //Der Einfachkeit wegen einfach kopiert
    userlib.c //Der Einfachkeit wegen einfach kopiert
    kernel.map //Der Einfachkeit wegen einfach kopiert
    user.ld //Wie von Erhard Henkes, s.o.
    start.asm //Wie von Erhard Henkes, s.o.
    test.c
    nasmw.exe //Der Einfachkeit wegen einfach kopiert
    mingw32-make.exe //Der Einfachkeit wegen einfach kopiert
    makefile
    build.bat
    

    test.c:

    #include "userlib.h"
    
    int main()
    {
        puts("TEST");
        return 0;
    }
    

    makefile:

    main: test.c userlib.c userlib.h
    	nasmw -O32 -f elf start.asm -o start.o 
    	i586-elf-gcc -c userlib.c -std=c99 -march=i386 -mtune=i386 -m32 -fno-pic -Werror -Wall -O -ffreestanding -fleading-underscore -nostdlib -nostdinc -fno-builtin -fno-stack-protector -Iinclude
    	i586-elf-gcc -c test.c -std=c99 -march=i386 -mtune=i386 -m32 -fno-pic -Werror -Wall -O -ffreestanding -fleading-underscore -nostdlib -nostdinc -fno-builtin -fno-stack-protector -Iinclude
    	i586-elf-ld *.o -T user.ld -Map user.map -nostdinc -o test.elf
    

    build.bat:

    mingw32-make main
    pause
    

    Nach dem ausführen von build.bat noch die elf-Datei in das Floppy-Image einfügen.

    Dann sollte es funktionieren und TEST auf den Bildschírm schreiben.


  • Mod

    Danke!



  • Analog zu den Funktionen putch und puts sollte es auch getch (schon vorhanden) und gets geben in der userlib


  • Mod

    PrettyOS funktioniert bei mir seit Revision 82 oder 81 nicht mehr. Es stürzt nach 1 sek. ab. Der Zug bleibt stehen, die Laufzeitangabe auch. Es nimmt keine Tastatureingaben an. (Eingabezeile ist aber schon da)
    Änderungen an der konfiguration der Virtuellen Maschine haben keine Verbesserungen gebracht.

    Danke für den Hinweis!
    Bitte teste das auch mit Sun Virtual Box auf das Image. Bei mir läuft das.
    qemu verwende ich unter Windows (Version von jidder, low level).

    Bei Cuervo (unser Cheftester) gibt es seit 81/82 auch Probleme.

    Was habe ich geändert?
    80 --> 81: diese mehrfachen 50ms-Delays weg, dadurch qemu mit Image sehr schnell (gut für Tests)
    81 --> 82: 1000 Hz ---> 100 Hz

    Rev. 82 läuft sowohl bei Cuervo als auch bei mir auf realer Hardware.


  • Mod

    Bitte HELLO.ELF (groß geschrieben) erzeugen wegen:

    tools/CreateFloppyImage2 PrettyOS FloppyImage.bin $(STAGE1DIR)/boot.bin $(STAGE2DIR)/BOOT2.BIN $(KERNELDIR)/KERNEL.BIN $(USERTEST)/HELLO.ELF

    im makefile
    (kann bei Linux Probleme geben, bei MS Windows lief es bisher)



  • Ändert man die Datei "hello.c" in Windows, lässt sich das Projekt auch nicht mehr kompilieren... scheinbar wird die HELLO.ELF gar nicht erst erstellt. Finde auch nichts dahingehend in der makefile.



  • Ich erzeug das Image sowieso manuell, daher war mir das nicht aufgefallen...


  • Mod

    hallo, rev. 84 liefert die erstellungswerkzeuge (build, makefile, tools, ...) in einem eigenen Unterordner mit. HELLO.ELF muss groß geschrieben werden, damit es in das FloppyImage eingebaut wird.


  • Mod

    Ich habe nu eine Funktion
    char* gets(char* s)
    in userlib.h/c eingefügt, aber es klappt leider noch nicht richtig im User-Programm.

    char* gets(char* s) ///TODO: leads to no success
    {
        int i=0;
        char c;
        do
        {
            c = getch();
            putch(c);
            if(c==8)  // Backspace
            {
               if(i>0)
               {
                  s[i]='\0';
               }
            }
            s[i] = c;
            i++;
        }
        while(c!=10); // Linefeed
        s[i]='\0';
        return s;
    }
    

    Separat getestet ist alles ok damit.

    In der Multitasking-Umgebung von PrettyOS geraten allerdings die Tasks und die Zeichen durcheinander. 🙄



  • Hallo!

    Habe mir einfach mal ein Programm gebastelt, was einfach nur den Screen löscht. Das compilieren und testen funktioniert wunderbar, bis... naja, bis ich's übertrieben habe... Ich habe dabei das Programm mehrmals hintereinander aufgerufen. Irgendwann (was die Anzahl betrifft nicht reproduzierbar) kam dann ein General Protection Fault...

    Hat jemand eine Idee woran das liegen könnte?

    #include "userlib.h"
    
    int main()
    {
    	unsigned long* vidmem = (unsigned long*) 0xb8000;
        unsigned long i=0;
        while(i<(40*25))
        {
            vidmem[i] = 0x07200720; // white on black, Space (0x20)
            ++i;
        };
    	return 0;
    }
    

  • Mod

    Das ist echt ein interessanter Punkt. So sieht bei mir momentan start.asm aus, das den Start und das Ende von main() der User-Test-Funktion im Verzecihnis user_test_c "umhüllt":

    ; start.asm
    
    [BITS 32]
    extern __bss_start
    extern __end
    extern _main
    extern _exit
    extern _test
    global _start
    
    _start:
        mov esp, 0x600000 ; stackpointer
        call _main	
    	call _test
    	call _exit	
    	call _test
    

    ... und nach mehrfachem Ausführen gelingt es odch tatsächlich, auch das zweite test() auszuführen. Dann kommt es logischerweise zum Absturz, so wie das Programm aufgebaut ist ohne jmp $ oder hlt!

    Mal braucht es nur drei "hello", mal ca. 10:
    screenshot: http://www.henkessoft.de/OS_Dev/Bilder/Rev87_mit_gets.PNG

    Weiß jemand, wie das passieren kann? Hat ja wohl mit dem Multitasking zu schaffen?


  • Mod

    Nun sieht start.asm so aus:

    ; start.asm
    
    [BITS 32]
    extern __bss_start
    extern __end
    extern _main
    extern _exit
    extern _test
    global _start
    
    _start:
        mov esp, 0x500000 ; stackpointer
        call _main	
    
    	call _exit	
    	call _test
    	jmp  $
    

    Man beachte den gegenüber der Shell (dort 0x600000) veränderten Stack-Pointer!


Anmelden zum Antworten