Forum: PC-Programmierung C-SnakeGame-Problem mit "Invalid Use of Register"


von Müller (Gast)


Angehängte Dateien:

Lesenswert?

Hallo liebes Forum,

mein Schulprojekt ist nun etwas weiter vorangeschritten. Ich habe 
mittlerweile den Kern des SnakeGame soweit fertig, zwar sind dort einige 
wirklich seltsame Bugs drinne, aber das ist erstmal egal.

Da ich noch eine kleine grafische Menüführung eingeplant hatte, habe ich 
mich zuerst mit dem ausgeben eines grafischen Textes befasst. Das 
funktioniert auch überraschend gut, wie ich finde.

Das Problem welches ich nun habe ist, dass ich ein paar Fehler beim 
Kompilieren bekomme und zwar 4x diesen hier:
1
"ccB6mnpQ.s|2153|Error: invalid use of register|"

Betreffende Zeile im Assembler Listing:
1
2153  lea rax, sP[rip]

Glücklicherweise lasse ich mir Assemblerlistings mitausgeben beim 
Debuggen, sonst hätt ich die Problematik nie erkannt.

Was dieser Fehler bedeutet ist mir relativ klar(nach Recherche), würde 
ich sagen, es bedeutet soviel wie:
Ich habe ein oder mehrere Prozessorregister benutzt, die eig. für andere 
Sachen vorgesehen sind. Z.b. RIP(Index Pointer?)

Jedoch ist mir nicht klar, wie ich das beeinflussen soll mit meinem 
C-Code.

In in der Datei SnakeSymbols.c - Funktion: SS_AddChar() - Ab Zeile: 419
befindet sich in der ellen langen Abfrage, 4 Auskommentierte Abfragen, 
die, wenn ich diese normal nutzen will, zu diesem besagten Fehler 
führen.

Hat jemand vielleicht eine Idee?

Konstruktive Kritik zum Code ansich, ist auch willkommen, solange die 
nicht bösartig rüberkommt! :)

Vielen lieben Dank!!


Gruß Müller

P.S. Es ist für Windows gemcht.

P.P.S. Ich habe mal einige meiner Dateien angehängt.

P.P.P.S. Ich bin kein Profi, wir machen es zurzeit in der 
Technikerschule, und müssen ein Projekt zum Ende des ersten Schuljahres 
machen. Bitte keine Flamings über meinen Stil oder sonstiger Sachen.

von Mark B. (markbrandis)


Lesenswert?

Müller schrieb:
> Ich habe ein oder mehrere Prozessorregister benutzt, die eig. für andere
> Sachen vorgesehen sind.

Nein. Wenn Du in reinem C programmierst, dann benutzt Du selbst bzw. 
Dein C-Code überhaupt keine Register. Das erledigt alles der Compiler.

Welchen Compiler in welcher Version verwendest Du?

: Bearbeitet durch User
von Müller (Gast)


Lesenswert?

CodeBlocks mit dem TDM-GCC

von Müller (Gast)


Lesenswert?

Entschuldigung hatte die Version vergessen, das müsste die Version: 
4.9.2 sein.

von nfet (Gast)


Lesenswert?

1
            if(sse2)
2
            {
3
                __m128i a, b;
4
5
                a = _mm_set_epi32(px, fx, py, fy);
6
                b = _mm_set_epi32(fx+sBLOCKSIZE, px+sBLOCKSIZE, fy+sBLOCKSIZE, py+sBLOCKSIZE);
7
8
                breakflag = _mm_movemask_epi8(_mm_cmplt_epi32(a, b)) == 0xFFFF;
9
            }

Hier oder bei einem ähnlichen Konstrukt dürfte wohl der Fehler liegen. 
Konnte es leider nicht herausfinden, da dein Code nicht wirklich 
portabel ist.
Sind denn die ganzen intrinsics notwendig?

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

In einem "snake-Programm" muss man unbedingt SSE2-Instruktionen 
verwenden. Klar.

von Mark B. (markbrandis)


Lesenswert?

Möglicherweise sind die Flags für den Compiler/Assembler bezüglich der 
Streaming SIMD Extensions nicht richtig gesetzt. Das könnte erklären, 
dass der Code nicht korrekt übersetzt werden kann.

Aber wie Rufus schon sagte: Braucht man das SSE Geraffel hier überhaupt? 
Ich würde das probeweise einfach mal auskommentieren und schauen ob es 
so geht.

: Bearbeitet durch User
von Müller (Gast)


Lesenswert?

Hallo Zusammen,

vielen Dank für das Feedback.

Jedoch liegt der Fehler nicht darin, dass ich SSE Instruktionen 
verwende, weil ich in meiner main.c nur die Funktionen meiner 
SnakeSymbols.c nutze und nicht die der SnakeGame.c. Jedoch habe ich dort 
alles ausgeklammert(auch die Includes) was mit den SSE Instruktionen zu 
tuen.

Resultat ist der selbe Fehler.

Um nochmal ganz konkret zu werden, der Compiler meckert wegen diesem 
Abschnitt(abgeleitet aus meinem Assembly-Listing)

SnakeSymbols.c - Zeile: 419
1
static bool SS_AddChar(char sign)
2
{
3
    // Checkup
4
    if(!sign || charcount > text)
5
        return false;
6
7
    // Upper Spell
8
    sign = SS_toUpper(sign);
9
10
    // Normalize Spells Nearest Neighboor / Bilinear Interpolating
11
    if(!BILINEAR)
12
    {
13
        // Vars
14
        Symbol new_sym[width*height];
15
        int x_ratio = (int)((rows<<16)/width) + 1;
16
        int y_ratio = (int)((clmn<<16)/height) + 1;
17
        int x2, y2, i, j;
18
19
        // Normalize using Nearest Neighboor
20
        // Algorithm from: Tech Algorithm
21
        // Article: http://tech-algorithm.com/articles/nearest-neighbor-image-scaling/
22
        for(i = 0; i<height; i++)
23
        {
24
            for(j = 0; j<width; j++)
25
            {
26
                x2 = ((j*x_ratio)>>16);
27
                y2 = ((i*y_ratio)>>16);
28
29
                // Choose Sign
30
                if(sign == 'A')
31
                    new_sym[(i*width)+j] = sA[x2][y2];
32
                else if(sign == 'B')
33
                    new_sym[(i*width)+j] = sB[x2][y2];
34
                else if(sign == 'C')
35
                    new_sym[(i*width)+j] = sC[x2][y2];
36
                else if(sign == 'D')
37
                    new_sym[(i*width)+j] = sD[x2][y2];
38
                else if(sign == 'E')
39
                    new_sym[(i*width)+j] = sE[x2][y2];
40
                else if(sign == 'F')
41
                    new_sym[(i*width)+j] = sF[x2][y2];
42
                else if(sign == 'G')
43
                    new_sym[(i*width)+j] = sG[x2][y2];
44
                else if(sign == 'H')
45
                    new_sym[(i*width)+j] = sH[x2][y2];
46
                //else if(sign == 'I')
47
                    //new_sym[(i*width)+j] = sI[x2][y2];
48
                else if(sign == 'J')
49
                    new_sym[(i*width)+j] = sJ[x2][y2];
50
                else if(sign == 'K')
51
                    new_sym[(i*width)+j] = sK[x2][y2];
52
                else if(sign == 'L')
53
                    new_sym[(i*width)+j] = sL[x2][y2];
54
                else if(sign == 'M')
55
                    new_sym[(i*width)+j] = sM[x2][y2];
56
                else if(sign == 'N')
57
                    new_sym[(i*width)+j] = sN[x2][y2];
58
                else if(sign == 'O')
59
                    new_sym[(i*width)+j] = sO[x2][y2];
60
                //else if(sign == 'P')
61
                    //new_sym[(i*width)+j] = sP[x2][y2];
62
                else if(sign == 'Q')
63
                    new_sym[(i*width)+j] = sQ[x2][y2];
64
                else if(sign == 'R')
65
                    new_sym[(i*width)+j] = sR[x2][y2];
66
                //else if(sign == 'S')
67
                    //new_sym[(i*width)+j] = sS[x2][y2];
68
                //else if(sign == 'T')
69
                    //new_sym[(i*width)+j] = sT[x2][y2];
70
                else if(sign == 'U')
71
                    new_sym[(i*width)+j] = sU[x2][y2];
72
                else if(sign == 'V')
73
                    new_sym[(i*width)+j] = sV[x2][y2];
74
                else if(sign == 'W')
75
                    new_sym[(i*width)+j] = sW[x2][y2];
76
                else if(sign == 'X')
77
                    new_sym[(i*width)+j] = sX[x2][y2];
78
                else if(sign == 'Y')
79
                    new_sym[(i*width)+j] = sY[x2][y2];
80
                else if(sign == 'Z')
81
                    new_sym[(i*width)+j] = sZ[x2][y2];
82
                else if(sign == ' ')
83
                    new_sym[(i*width)+j] = sSP[x2][y2];
84
                else
85
                    new_sym[(i*width)+j] = sSP[x2][y2];
86
            }
87
        }
88
89
        // Putting it into RenderTarget
90
        for(i = 0; i<width*height; i++)
91
        {
92
            RenderTarget[(charcount*width*height)+i] = new_sym[i];
93
        }
94
95
    }
96
97
    charcount++;
98
99
    return true;
100
}

Dort kann man sehen, dass ich 4 Abfragen ausgeklammert habe. Wenn ich 
die Ausklammerung weg mache, kommt der oben genannte Fehler. Wenn ich 
alles normal lasse, sind es dementsprechend 4 dieser Fehler.

Der Grund warum ich im SnakeGame.c SSE Instruktionen verwende, ist 
einfach nur weil ich testen wollte, ob man eine IF-Abfrage in SSE 
nachbilden kann, was offensichtlich funktioniert, da ich in diesem Fall 
auch 4 Abfragen in der IF-Abfrage habe, ist das in diesem Falle ja schon 
super "Vectorized".

Ich hatte ja noch vor, die ganzen (x*y+z) Rechnungen in meinem Code, 
mittels XOP(_mm_macc_epi32) nachzubilden und später zu "Vectorizieren".
Zum Glück hab ich das noch nicht gemacht, sonst hättet ihr mich 
gehasst^^
Warum sollte man solche Instruktionen nicht verwenden, wenn Sie 
vorhanden sind? Dafür sind die doch gemacht worden^^

Egal, zurück zum Thema. Jemand eine Idee woran es liegt? Ich habe im 
Internet gelesen, dass das auch häufiger Compiler Bugs sind?!

Vielen lieben dank!

Gruß Müller

von Müller (Gast)


Lesenswert?

Hallo nochmal,

ich habe den Fehler behoben!!
Unglaublich aber war, ich denke es war definitiv ein Compiler-Bug!

Und zwar habe ich das Problem wie folgt gelöst(^^):
1
static Symbol sPP[7][7] = {
2
                           {CA, CA, CA, CA, CA, CA, CA},
3
                           {CA, CB, CB, CB, CB, CA, CA},
4
                           {CA, CB, CA, CA, CA, CB, CA},
5
                           {CA, CB, CB, CB, CB, CA, CA},
6
                           {CA, CB, CA, CA, CA, CA, CA},
7
                           {CA, CB, CA, CA, CA, CA, CA},
8
                           {CA, CA, CA, CA, CA, CA, CA}
9
                         };
10
--------------------------------------------------------------
11
else if(sign == 'P')
12
                    new_sym[(i*width)+j] = sPP[x2][y2];

Ich habe einfach den Variablen Namen von den angemeckerten Symbolen 
einfach geändert, in diesem Falle von "sP" -> "sPP".

Vielleicht war der Compiler irritiert und hat gedacht "sP" würde 
stackpointer bedeuteten oder so.

Danke sehr an alle!!

Gruß Müller

von physiker (Gast)


Lesenswert?

Müller schrieb:
> ich habe den Fehler behoben!!
> Unglaublich aber war, ich denke es war definitiv ein Compiler-Bug!

Die Wahrscheinlichkeit dafür geht stark gegen 0%.

von Rolf M. (rmagnus)


Lesenswert?

Müller schrieb:
> Warum sollte man solche Instruktionen nicht verwenden, wenn Sie
> vorhanden sind? Dafür sind die doch gemacht worden^^

Die sind dafür gemacht worden, um Programme, die Millionen von 
Vektoroperationen pro Sekunde machen müssen, zu beschleunigen.
Die nutzt man daher eigentlich nur, wenn man durch sie auch tatsächlich 
einen signifkanten Geschwindigkeitsgewinn hat.
Man geht ja auch nicht extra in einen Operationssaal und nimmt den 
Chefarzt mit, um sich ein Pflaster auf den Finger zu kleben.

von Hans (Gast)


Lesenswert?

Ich würde die Symbole bzw. Zeiger darauf in ein Array packen und in 
SS_AddChar einfach den Index ausrechnen (sign - 'A'). Damit wird aus der 
ewigen if/else-Kette eine Zeile.

von Müller (Gast)


Angehängte Dateien:

Lesenswert?

@Hans
Vielen Dank für den Hinweis. Hat super funktioniert.
Macht den Code auch etwas kürzer.

@Rolf
Du hast natürlich recht, aber wer würde nicht gern vom Chefarzt eine 
Behandlung bekommen?^^

@Physiker
Dann erkläre mir woran es sonst liegt? Steht irgendwo dass ich z.B. den 
Variablennamen "sP" nicht benutzen darf?

Anbei nochmal die aktuellste Variante.

Gruß

von Vlad T. (vlad_tepesch)


Lesenswert?

physiker schrieb:
> Die Wahrscheinlichkeit dafür geht stark gegen 0%.

nee, je nach Verbreitung des Compilers, is das nicht so 
unwahrscheinlich.

In Blackfin oder TriCore C-Compilern, hab ich auch schon Bugs gefunden 
^^.

Nur is das ja normalerweise das Letzte, wo man einen Bug vermutet - 
entsprechend lange heben die Suchen jeweils gedauert.

: Bearbeitet durch User
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.