Lowlevel
Lowlevel => OS-Design => Thema gestartet von: najjannaj am 20. May 2004, 19:44
-
Hi,
Hab folgendes Problem beim Kompilieren:
mem.c: In function `count_memory':
mem.c:26: Invalid `asm' statement:
mem.c:26: fixed or forbidden register 0 (ax) was spilled for class AREG.
mem.c:34: Invalid `asm' statement:
mem.c:34: fixed or forbidden register 0 (ax) was spilled for class AREG.
mem.c:63: Invalid `asm' statement:
mem.c:63: fixed or forbidden register 0 (ax) was spilled for class AREG.
Hab keinen Plan warum das jetzt nicht funktioniert! Kann mir einer von euch Helfen???
Hier die "mem.c":
#include "include\io.h"
#include "include\mem.h"
unsigned long mem_end, bse_end;
void count_memory(void)
{
register unsigned long *mem;
unsigned long mem_count, a;
unsigned short memkb;
unsigned char irq1, irq2;
unsigned long cr0;
/* save IRQ's */
irq1=inportb(0x21);
irq2=inportb(0xA1);
/* kill all irq's */
outportb(0x21, 0xFF);
outportb(0xA1, 0xFF);
mem_count=0;
memkb=0;
// store a copy of CR0
__asm__ __volatile("movl %%cr0, %%eax":"=a"(cr0)::"eax");
// invalidate the cache
// write-back and invalidate the cache
__asm__ __volatile__ ("wbinvd");
// plug cr0 with just PE/CD/NW
// cache disable(486+), no-writeback(486+), 32bit mode(386+)
__asm__ __volatile__("movl %%eax, %%cr0" :: "a" (cr0 | 0x00000001 | 0x40000000 | 0x20000000) : "eax");
do
{
memkb++;
mem_count+=1024*1024;
mem=(unsigned long *)mem_count;
a=*mem;
*mem=0x55AA55AA;
// the empty asm calls tell gcc not to rely on whats in its registers
// as saved variables (this gets us around GCC optimisations)
asm("":::"memory");
if(*mem!=0x55AA55AA)
mem_count=0;
else
{
*mem=0xAA55AA55;
asm("":::"memory");
if(*mem!=0xAA55AA55)
mem_count=0;
}
asm("":::"memory");
*mem=a;
}while(memkb<4096 && mem_count!=0);
__asm__ __volatile__("movl %%eax, %%cr0" :: "a" (cr0) : "eax");
mem_end=memkb<<20;
mem=(unsigned long *)0x413;
bse_end=((*mem)&0xFFFF)<<6;
outportb(0x21, irq1);
outportb(0xA1, irq2);
}
und hier die "mem.h":
#ifndef MEM_INCLUDE
#define MEM_INCLUDE
extern unsigned long mem_end, bse_end;
void count_memory();
#endif
-
Benutzt Du gcc? Dann würden die Register fehlen, die Du änderst.
-
Ja, ich benutze gcc und ld, sowie nasm. Wo trag ich die Register ein und wie leg ich diese fest??
Danke!
-
Wenn Du bei Inline-ASM in gcc Register veränderst musst Du das dem Compiler mitteilen:
Der Compiler will Inline-ASM in folgender Form:
asm ("Assemblercode";
: Ausgabeoperanden-Spezifikation
: Eingabeoperanden-Spezifikation
: Modifizierte Register
);
Das Beispiel setzt b=a:
int move()
{
int a = 5;
int b;
asm("mov %1, %%eax;
mov %%eax, %0;"
: "=r"(b) /* Ausgaberegister */
: "r" (a) /* Eingaberegister */
: "%eax"); /* Modifizierte Register */
printf("B: %u\n", b);
}
Also:
"=r" legt fest, dass für b ein Register benutzt werden soll. Das Register sucht sich der Compiler selbst aus. Angesprochen wird das erste Register, dass der Compiler auswählt mit %0. Der Inhalt des Registers soll im Anschluß in die Variable b gespeichert werden.
"r" legt fest, dass für den a ein Register benutzt werden soll. Das Register ist hier das zweite genannte, also %1.
"%eax" bedeutet hier, dass das Register %eax vom Inline-ASM benutz wird.
Und es ist egal ob man __ASM__ oder asm als Schlüsselwort verwendet.
Das Beispiel ist entnommen aus dem Anhang des Buches Linux Kernelarchitektur. http://www.linux-kernel.de/appendix/index.html
Ich hoffe ich konnte Dir helfen.
-
Vielen Dank! Werd gleich Testen und dann nochmal bescheid sagen!
Danke!