Gå til innhold

Problem: Flat binær kompilasjon med GCC (MinGW)!


Anbefalte innlegg

Skrevet (endret)

Jeg kan litt C, og tenkte jeg skulle lage ett par små kernels som jeg kan laste over på en floppy, bare for morroskyld, men jeg har en del problemer med compileren her. Har lasta ned GCC MinGW, som er en bra C kompiler, som kjører på NT, men den nekter meg å linke objekt filer jeg vil ha ut som flat binary (uten headers for hverken Windows, Linux, eller noe, bare CPU kode fra starten med unntak av strings, og andre ressurser).

 

Jeg lagde en kernel som ikke gjør en drit først for å se om compileren kompilerer:

 

int main()
{
 return 0;
}

 

 

Den gjør ikke mye den, hehe :), however, når jeg prøver å compile den med disse kommandoene, går det ikke:

 

gcc -c test.c

ld test.o -o test.bin --oformat binary -Ttext $100000

 

Resultatet:

ld: PE operations on non PE file.

 

 

Why? Den lille .c fila har jo ingen PE kode, og jeg prøver ikke å gjøre en PE operasjon jeg. Alt jeg gjør er å kompilere en C fil som ikke gjør en dritt, om til flat binary, som også bare ville halta PC'en hvis jeg prøvde å starte opp med den.

 

Har lest at dette kanskje er en bug i LCC for Windows. Er det sant? Workarounds?

Endret av chrml
Videoannonse
Annonse
Skrevet

Tror jeg eller daysleper har svart på dette i en tidligere tråd - sitter ikke inne med informasjonen nå sånn uten videre.

 

Hvis du absolutt ikke finner ut av det kan jeg ta meg sammen og se om jeg får rota frem noe.

Skrevet (endret)

gcc -ffreestanding -c test.c

 

^- Den fjerner alle "precompiled headers", og gir deg en ren binær fil.

Tror dette skal funke.

 

Du er ikke den eneste som har prøvd dette :D

Det er drittgøy, for når du skriver alt fra scratch, så lærer du hvordan alt funker også, selv om det kan være litt vanskelig.

 

EDIT: Og ja, det er TO f'er. Ikke leif.

Endret av kr1570ffz0r
Skrevet (endret)

Hehe, yep :).

 

Skal prøve dette nå :D.

 

ADDED: Hehe, great, det funka :). Skal prøve å boote denne kernelen seinere i dag, må skru inn noen PCI kort først bare.

Endret av chrml
Skrevet
gcc -ffreestanding -c test.c

 

^- Den fjerner alle "precompiled headers", og gir deg en ren binær fil.

Tror dette skal funke.

 

Du er ikke den eneste som har prøvd dette :D

Det er drittgøy, for når du skriver alt fra scratch, så lærer du hvordan alt funker også, selv om det kan være litt vanskelig.

 

EDIT: Og ja, det er TO f'er. Ikke leif.

En ting, det der, creater ikke det en objekt fil, og ikke det ferdige kompilerte resultatet?

 

Isåfall, ld.exe klager enda på "PE operations on non PE file".

 

Åpna test.o som blei resultatet, og det så veldig ut som en objekt fil (hadde til og med stringen test.c inni seg).

Skrevet

Her er noe jeg fannt som ser ut til å kompilere som det skal under Linux (GCC-3.4.0):

 

Kernel.cpp:

#include "Video.h"

int main(void)
{
       Video vid;  //local, (global variables need some Run-Time support code)

       vid.write("Hello, world!");
}

 

Link.ld:

OUTPUT_FORMAT("binary")
ENTRY(start)
SECTIONS
{
   .text 0x100000 :
   {
       code = .; _code = .; __code = .;
       *(.text)
       . = ALIGN(4096);
   }

   .data :
   {
       data = .; _data = .; __data = .;
       *(.data)
       . = ALIGN(4096);
   }

   .bss :
   {
       bss = .; _bss = .; __bss = .;
       *(.bss)
       . = ALIGN(4096);
   }

   end = .; _end = .; __end = .;
}

 

Loader.asm:

[BITS 32]; protected mode

[global start]
[extern main]; this is in our C++ code

start:
call main; call int main(void) from our C++ code
cli; interrupts could disturb the halt
hlt; halt the CPU

 

Video.cpp:

#include "Video.h"

Video::Video()
{
       pos=0;        off=0;
       videomem = (unsigned short*) 0xb8000;
}

Video::~Video() {}

void Video::clear()
{
       unsigned int i;

       for(i=0; i<(80*25); i++)
       {
               videomem[i] = (unsigned char) ' ' | 0x0700;
       }
       pos=0; off=0;
}

void Video::write(char *cp)
{
       char *str = cp, *ch;

       for (ch = str; *ch; ch++)
       {
               put(*ch);
       }
}

void Video::put(char c)
{
       if(pos>=80)
       {
               pos=0;
               off += 80;
       }

       if(off>=(80*25))
       {
               clear(); //should scroll the screen, but for now, just clear
       }

       videomem[off + pos] = (unsigned char) c | 0x0700;
       pos++;
}

 

Video.h:

#ifndef VIDEO_H
#define VIDEO_H        //so we don't get multiple definitions of Video

class Video
{
public:
       Video();
       ~Video();
       void clear();
       void write(char *cp);
       void put(char c);
private:
       unsigned short *videomem;   //pointer to video memory
       unsigned int off;                    //offset, used like a y cord
       unsigned int pos;                  //position, used like x cord

}; //don't forget the semicolon!

#endif

 

Kompilering:

g++ -c Video.cpp -nostdlib -fno-builtin -fno-rtti -fno-exceptions

g++ -c Kernel.cpp -nostdlib -fno-builtin -fno-rtti -fno-exceptions

nasm -f aout Loader.asm -o Loader.o

 

Linking:

ld -T Link.ld -o Kernel.bin Loader.o Kernel.o Video.o

 

Regner med at det fungerer med MinGW (GCC) under Win32 også.

Skrevet

Wooohoo!

 

Lasta ned DJGPP, nyeste versjon, og kompilerte din sample med den. Det funka (det gjorde ikke det med MinGW). :) Thanks.

Skrevet
gcc -ffreestanding -c test.c

 

^- Den fjerner alle "precompiled headers", og gir deg en ren binær fil.

Tror dette skal funke.

 

Du er ikke den eneste som har prøvd dette :D

Det er drittgøy, for når du skriver alt fra scratch, så lærer du hvordan alt funker også, selv om det kan være litt vanskelig.

 

EDIT: Og ja, det er TO f'er. Ikke leif.

En ting, det der, creater ikke det en objekt fil, og ikke det ferdige kompilerte resultatet?

 

Isåfall, ld.exe klager enda på "PE operations on non PE file".

 

Åpna test.o som blei resultatet, og det så veldig ut som en objekt fil (hadde til og med stringen test.c inni seg).

Det var bare et eksempel.

Skrevet (endret)
Ang. booting og sånnt, ta en titt her: http://bochs.sourceforge.net/

 

Kan spare deg for masse-masse tid. :]

Jeg bruker en test-maskin som booter kjappere enn lynet,

det er en gammal PackardBell PIII, 500 mhz med 384 mb ram,

som jeg brukte før.

 

Men uansett kan det jo være verd et forsøk, jeg må jo faktisk flytte meg et stykke for å komme til den andre maskinen, hele 5 meter faktisk :cool:

 

EDIT: Sorry for dobbelpost, det tenkte jeg ikke på :blush:

Endret av kr1570ffz0r
Skrevet (endret)

Thanks for hjelpa :)!

 

Har ett lite problem though. Akkurat nå prøver jeg å boote kernelen min fra en floppy. Først prøvde jeg å laste den 512 byte svære kernel fila mi inn i floppyens sektor 0 (kompilert med søppels eksempelkode), og la til 55AA på slutten for at den skal boote. Den boota, men den frøys opp maskina, og jeg veit hvorfor. Asm koden er kompilert 32 bit, mens jeg tviler på at Bootstar enabler Protected Mode før den prøver å laste kernelen, så derfor funka ikke det.

 

Da tenkte jeg på koden:

 

[BITS 16];starte i 16 bit

[global start]
[extern _k_main]; this is in the c file

start:
 mov eax, cr0;for å enable protected mode
 or al,1
 mov cr0,eax

 [BITS 32];gå over til 32 bit

 call _k_main;og kjøre main funksjonen i C

 cli
 hlt

 

However, jeg kan ikkeno asm (helt blank), så jeg veit ikke om det jeg kokte sammen faktisk kan funke.

 

Hvis det ikke gjør det, åssen kan jeg laste sektor 1 inn i minnet, og jumpe dit i asm, så jeg kan ha 32 bit koden der?

Endret av chrml
Skrevet

Vet ikke helt hva som foregår, men du er klar over at du må ha en eller annen bootloader før kernelen kommer inn i bildet?

 

Grub f.eks.

Skrevet (endret)

Yep, men egentlig alt den bootloaderen gjør (hvertfall fra floppy) er å loade kernelen inn i minnet (ved å tolke filsystemet, eller å loade fra en spesiell posisjon), switche til protected mode, og så jumpe til minnet den lasta kernelen inn i.

 

For å gjøre dette simpelt foreløpig, tenkte jeg at jeg skulle plassere en liten kernel på sektor 1, og lage en bootloader (16 bit (real kompatibel) i asm, som jeg ikke kan en drit i) på sektor 0 som switcher over til protected mode, laster kernelen fra sektor 1 i minnet (på 1mb streken, kanskje), og jumpe dit.

 

Prøvde GRUB, men skjønte ikke mye av åssen den funker.

Endret av chrml
Skrevet (endret)

Bootloaderen er jo simpel, den, det er jo bare å følge en tutorial første gangen, men saken er at bootloaderen har kanskje mye å gjøre, og da må du lage bootstrap (som noen kaller det) også. Det bootloaderen vil gjøre da, er å laste bootstrap'en inn i minnet, og deretter vil bootstrapen laste kernelen. Jeg har fått til å laste kernelen UFORSKYLDT, jeg bare prøvde meg litt frem, siden tutorialen jeg fulgte sluttet rett før jeg skulle jumpe inn i protected mode og laste kernelen. Men jeg tror jeg lærer meg litt mer assembly før jeg fortsetter mer med dette :roll:

 

EDIT: http://www.osdev.org/

Endret av kr1570ffz0r
Skrevet
Wooohoo!

 

Lasta ned DJGPP, nyeste versjon, og kompilerte din sample med den. Det funka (det gjorde ikke det med MinGW). :) Thanks.

Snålt, det funket ikke med meg heller :lol:

Skrevet (endret)

Hehe, detta er gøy.

 

Jeg anbefaler ALLE som har litt programmering og PC kunnskaper til å prøve detta. Det er pain in the ass å få det til første gang, men seinere går det som bare det.

 

I går kunne jeg lite C, og ikkeno Assembly, og sleit med å boote dette. I dag skriver jeg C funksjoner til OS kernelen min som bare det, og kjører det på emulatoren med ett trykk :) (.bat filer), og hvis jeg gidder, også ordentlig boote kernelen med floppy.

 

Lage OS med DJGPP (C kompiler), og Nasm (assembler), anbefales på det sterkeste :D.

Endret av chrml

Opprett en konto eller logg inn for å kommentere

Du må være et medlem for å kunne skrive en kommentar

Opprett konto

Det er enkelt å melde seg inn for å starte en ny konto!

Start en konto

Logg inn

Har du allerede en konto? Logg inn her.

Logg inn nå
  • Hvem er aktive   0 medlemmer

    • Ingen innloggede medlemmer aktive
×
×
  • Opprett ny...