ďťż

Ładny brzuch

Przeczytałem pewien kurs w internecie pisania kernela systemu operacyjnego (kurs) i według instrukcji napisałem wszystkie źródła (pominąłem część kursu dot. obiektów globalnych) , jednak linker LD.EXE podczas kompilacji zwraca mi błędy:

Kernel.o:Kernel.cpp:(.text+0x15): undefined reference to `__alloca'
Kernel.o:Kernel.cpp:(.text+0x1a): undefined reference to `___main'

Nie wiem, czy to wina skryptu linkera (*.ld). Może ktoś potrafi mi pomóc?

a kompilatora, czy co? nadal błędy mimo przepisania kodu literka w literkę.
Użytkownik Miłek27 edytował ten post 02 luty 2007, 09:34


Przed nazwami procedur daj: _

Ale w pliku kernel.cpp? tam mam tylko funkcję 'int main'. Rozwiąże to problem z tym __alloc?

Problem z linkerem jak sądzę. Twój program z założenia niema, co więcej nie może mieć funkcji _alloca i __main!!

Sprawdź jeszcze raz czy dobrze przepisałeś skrypt linkera i czy dobrze go uruchamiasz! To "-T" jest duże, bo może tu popełniłeś błąd, bo "-t" znaczy co innego. Pliki ".o" też muszą być w dobrej kolejności - ten spod nasma musi być pierwszy.

//edit:
@niżej: głowy za to nie dam, drugi raz w życiu widzę taki skrypt :D. Te z mingw są dużo bardziej rozbudowane i nie chciało mi się ich "rozumieć" = uczyć się
//edit:
che :D przepisałem tego kernela...

loader.o:loader.o:(.text+0x1): undefined reference to `_main' :roll1:
ale nie mam err co do alloca!

//edit:
kompiluje się i linkuje bez problemu, ale czy działa to nie wiem, ponieważ ten kod niema boot loadera - trzeba go samemu dorobić :( - a mi się już odechciało grzebać... Cały trik polega na tym, że niktóre kompilatory dodają "_" przed nazwą funkcji, a niektóre nie. Ten kod działa na "g++". Co do twojego błędu, to myślę, że masz zły kod w pliku "kernel.cpp" choć twojego pliku nie widziałem. (zdaje mi się, że wkleiłeś tam "standardowy" kod c++, tzn. taki jak gdybyś miał bibliotekę runtime i z tąd ten "alloca" ale to tylko domysły)

"video.h"
#ifndef video_h #define video_h class video { public: video(); ~video(); void clear(); void write(char *cp); void put(char c); private: unsigned short *videomem; unsigned int off; unsigned int pos; }; #endif
"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(); } videomem[off + pos] = (unsigned char) c | 0x0700; pos++; }
"kernel.cpp"
#include "video.h" int main(void) { video vid; 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] [global start] [extern main] start: call main cli hlt
Użytkownik Radek edytował ten post 31 styczeń 2007, 14:23


Teraz nie jestem u siebie na kompie ale sprawdzę, gdyż mam wątpliwości co do kolejności plików, nieco mniejsze do tego T. A skrypt linkera z tego kursu jest prawidłowy?

//edit

to skąd wziąc porządny skrypt?
(nie za bardzo rozumiem, ale mingw i djgpp mam)

//edit2

Ten alloc to sam nie wiem skąd się wziął. Poradą kolegi strefacst dopisałem w kernel.cpp do main podkreślenie, czyli _main i został mi sam błąd z loader.asm że nie widzi funkcji main. Ale mówisz że na g++? Z kursu wynikało, że na gxx, próbowałem też na gcc (wybacz głupotę, ale nie posiadam linuxa i nie znam kompilatorów, choć mam zamiar to radykalnie zmienić). Skompilować to wszystko w g++? Spróbuję. Dzięki za fatygę!

//edit

No nie wiem, czy to wina kompilatora? nadal nie działa... :(
Użytkownik Miłek27 edytował ten post 02 luty 2007, 09:35
Funkcja main z kernel.cpp niema nic wspólnego z tym błędem!

W normalnym programie system wywołuje funkcję _ _ main w naszym programie, a ta inicjalizuje exeka i dopiero wtedy wywołuje int main() (tak w uproszczeniu)
Tutaj loader.asm jest ładowany binarnie przez np. gruba (trzeba dorobić kod) i asmowe call _main wywołuje funkcję main z kernel.cpp - tak! _main wywołuje main, bo standardowe kompilatory c++ (w windows) dodają podkreślenie do nazwy funkcji przy kompilacji - czyli w binarnym kodzie _main z asm ma wywołać _main z cpp.*
Błąd pokazuje (jak dobrze kojażę), że niema w naszym kodzie odwołania do ___main bo nie może być - napisałem to wyżej, kod asm'a jest ładowany binarnie - oraz nie ma odwołania do alloca bo ta funkcja służy do zarządzania pamięcią (dokładniej stosem) i znajduje się w bibliotekach runtime które specjalnie zostały wywalone (taka jest intencja, a jak widać jest błąd) bo zależą od os'a więc musielibyśmy je napisać sami, więc bez nich jest prościej.

Teraz dopisując w kernel.cpp przed 'main' '_' spowodowałeś że ta funckja po kompilacji wygląda tak: "_ _ main" (spacje wstawione specjalnie), a z asma wywołujesz "_ main" więc nic dziwnego, że wywala błąd z pliku loader: main z asm nie może znaleść main z kernel.cpp! Tutaj się kompilacja (linkowanie?) zatrzymuje i dla tego niema błędów z _alloca i __main.

*w poście wyżej widać, że w kodzie loader.asm niema podkreśleń. Jest tak dlatego, że był on kompilowany w linuksie, a tu kompilator cpp nie dodaje podkreśleń do nazw funkcji...
____________________________________
Do głównego problemu: albo kompilator cxx dodaje niepotrzebne biblioteki do .o, albo linker na siłę szuka funkcji _alloca i __main. Co dokładnie to nie mam już ochoty sprawdzać, może ktoś bardziej doświadczony sie wypowie...

  • zanotowane.pl
  • doc.pisz.pl
  • pdf.pisz.pl
  • zsf.htw.pl
  •