Lowlevel
Lowlevel => Lowlevel-Coding => Thema gestartet von: RedEagle 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??
-
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
-
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 ??
-
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));
-
welche gcc version verwendest du?
ich bekomm einen internal-compiler error.
-
gcc 4.1.0
-
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.
-
@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
-
Also in LOST habe ich es so geschrieben, was auch am direktesten der Spezifikation entspricht:
asm("lidt %0" : : "m" (idt_ptr));
-
das tut was es soll :)