Autor Thema: Problem mit inlineassambler und lidt  (Gelesen 6370 mal)

RedEagle

  • Beiträge: 244
    • Profil anzeigen
    • RedEagle-OperatingSystem - Projekt
Gespeichert
« am: 29. December 2005, 09:48 »
Mein code:
INTERRUPT idt[256];
DWORD     ptr_idtr[3];

bool LoadIDT()
{
 ptr_idtr[0] = (sizeof(INTERRUPT)*256) << 16;
 ptr_idtr[1] = (DWORD)idt;
 
 __asm__ __volatile__ ("LIDT (%0) ": :"p" (&ptr_idtr[3]) );

 return true;
}


Bei dem asm-teil gibts ein Linkererror:
\idt.obj(.text+0x4e):idt.cpp: undefined reference to '$_ptr_idtr'
\idt.obj(.text+0x260):idt.cpp: undefined reference to '$_ptr_idtr'


Wenn ich den asm-teil rauskommentiere gibt's keine Probleme...

Wo ist mein Fehler??

Jidder

  • Administrator
  • Beiträge: 1 625
    • Profil anzeigen
Gespeichert
« Antwort #1 am: 29. December 2005, 12:10 »
Hi,

das Problem ist, dass ptr_idtr global ist. Wenn GCC den Assemblercode erzeugt landet der Datenteil (also die globalen Variablen) unter dem Code-Teil und sind damit anscheinend für den Assembler nicht sichtbar. Die einfachste Lösung ist ptr_idtr in den scope der Funktion zu setzen.

Außerdem glaube ich dass &ptr_idtr[3] falsch ist. Sollte das vielleicht (char*)ptr_idtr + 2 heissen? ;) Ich würde sowieso ein struct für die idtr empfehlen und nicht mit irgendwelchen Arrays rumfummeln. Das << 16 und &ptr_idtr[3] (bzw. (char*)ptr_idtr + 2) sind ja schon genug Argumente dagegen.

PorkChicken
Dieser Text wird unter jedem Beitrag angezeigt.

RedEagle

  • Beiträge: 244
    • Profil anzeigen
    • RedEagle-OperatingSystem - Projekt
Gespeichert
« Antwort #2 am: 21. January 2006, 20:52 »
sry für die Späte antwort, hatte aber in letzter Zeit andere Probleme...

Ich habe jetzt ein sturct genommen:

typedef struct
{
 WORD       limit;
 INTERRUPT *base;
} __attribute__ ((packed)) IDTR;


IDTR idtr;

//-----------------------------------------------------------------------------------

bool LoadIDT()
{
// static IDTR idtr;
 idtr.limit = (sizeof(INTERRUPT)*256)-1;
 idtr.base  = idt;

 IDTR *pidtr = &idtr;
 asm volatile ("LIDT (%0) ": :"p" (pidtr)); //undefined reference to $_idtr

 return true;
}


immernoch undefined reference...
Wenn ich idtr lokal mache (wie hier wegkommentiert ist) lässt es sich zwar kompilieren, habe aber die Selbe reaktion als wenn ich es Global mache, und den asm-teil weglasse (beides verursacht einen reboot)

Ich bin langsam am verzweifeln.

Ich habe mir mal den Code von "Pirat" angesehen, (wie man an meinem code evtl sieht ;) ) und da scheint es so zu funktionieren... warum aber bei mir nicht ??

RedEagle

  • Beiträge: 244
    • Profil anzeigen
    • RedEagle-OperatingSystem - Projekt
Gespeichert
« Antwort #3 am: 05. September 2007, 14:37 »
Der Beitrag ist zwar schon alt, aber:...

Ich überarbeite meinen kernel momentan, und dabei kam es erneut zu dem oben genannten Problem.

Da noch keine Lösung gepostet wurde, und evtl andere leute selbiges Problem haben/bekommen, möchte ich die Lösung des Problems posten.

Das Problem liegt an der inline-assembler-zeile.
Die muss wie folgt lauten:

asm volatile ("LIDT (%%eax) ": :"p" (pidtr));

middle_endian

  • Beiträge: 25
    • Profil anzeigen
Gespeichert
« Antwort #4 am: 05. September 2007, 17:44 »
welche gcc version verwendest du?
ich bekomm einen internal-compiler error.

RedEagle

  • Beiträge: 244
    • Profil anzeigen
    • RedEagle-OperatingSystem - Projekt
Gespeichert
« Antwort #5 am: 05. September 2007, 18:22 »
gcc 4.1.0

MNemo

  • Beiträge: 547
    • Profil anzeigen
Gespeichert
« Antwort #6 am: 06. September 2007, 15:53 »
also mit gcc 4.1.3
würde die Zeile
asm volatile ("LIDT (%%eax) ": :"p" (pidtr));zu einem Fehler führen(der wegen compiler optimierungen möglicher weise erst nach anderen änderungen 'sichtbar' wird), weil eax nicht mit pidtr initialiesiert wird.

Deshalb würde ich es folgender maßen machen.
asm volatile ("LIDT (%0) " : : "r" (pidtr)); das funktioniert auf jeden fall, weil zu erst ein register 'x' mit pidtr geladen wird und dann dann mit 'lidt ' benutzt wird.
„Wichtig ist nicht, besser zu sein als alle anderen. Wichtig ist, besser zu sein als du gestern warst!“

middle_endian

  • Beiträge: 25
    • Profil anzeigen
Gespeichert
« Antwort #7 am: 06. September 2007, 21:40 »
@MNemo: das hab ich auch versucht, allerdings gibts da auch einen internal compiler-error.
idt.cpp:57: internal compiler error: in emit_move_insn, at expr.c:3096
g++-version 4.0.3

kevin

  • Administrator
  • Beiträge: 2 767
    • Profil anzeigen
Gespeichert
« Antwort #8 am: 06. September 2007, 21:45 »
Also in LOST habe ich es so geschrieben, was auch am direktesten der Spezifikation entspricht:
asm("lidt %0" : : "m" (idt_ptr));
Thou shalt not follow the NULL pointer, for chaos and madness await thee at its end.

middle_endian

  • Beiträge: 25
    • Profil anzeigen
Gespeichert
« Antwort #9 am: 06. September 2007, 23:43 »
das tut was es soll :)

 

Einloggen