www.mikrocontroller.net

Forum: Mikrocontroller und Elektronik [ASM] PowerPC springt nach 0x0


Autor: Udo (Gast)
Datum:

Hallo,

in meinem PowerPC (56xx) Programmablauf kommt es nach gewisser Zeit zu
einem falschen Programmablauf. Und zwar springt er zu Adresse 0x0.
Die Ursache für diesen Sprung ist in diesen Zeilen zu finden:
..
....
lwzx     r3,r3,r0  ; schreibe 0 nach r3
se_mtctr r3        ; schreibe r3 nach CTR (Count Register)
se_bctr            ; branch zu CTR

Kann mir jemand sagen, was das für einen Sinn haben soll?
An Adresse 0x0 steht das Reset Configuration Half Word (RCHW) =
0x015A0000.
Da wird er wohl kaum hinspringen wollen.


Ich glaube, dass r3 einfach nicht 0 sein darf - aber nur eine Vermutung.
Wie die Null zu stande kommt sieht man wie folgt. Hier also der ganze
Abschnitt:
                    ; r0 = 0x0003A360
                    ; r1 = 0x40003E2F
se_lhz r0,0x10(r1)   ; nach diesem Schritt ist r0 gleich 0
se_cmpli r0,0x8
se_bgt 0x37A1E
e_lis r8,0x40000000
e_add16i r3,r8,0x1CD8
se_slwi r0,0x2
lwzx     r3,r3,r0  ; schreibe 0 nach r3
se_mtctr r3        ; schreibe r3 nach CTR (Count Register)
se_bctr            ; branch zu CTR


Ich verstehe hier nicht, wass der ASM mit
se_lhz r0,0x10(r1)
macht. Was bedeutet diese Zeile?
Autor: TManiac (Gast)
Datum:

Hi Udo,

wenn ich mich richtig erinnere holt deine Zeile einen Wert aus der
Speicherzelle, welche durch R1 plus 0x10 adressiert wird. In deinem
Codeschnippsel steht darüber dass r1 = 0x40003E2F ist. Also wird der
Wert aus dem RAM geholt. Entweder hast du vergessen eine Initfunktion
aufzurufen. Oder es Mangelt an einer Routine zum Kopieren, der
vorinitialisierten Variablen.

Gruß,
TManiac
Autor: Udo (Gast)
Datum:

ok, er holt sich den Wert aus 0x40003E2F + 0x10 = 0x40003E3F.
Dort steht 0x40 drin. Warum er denkt, es wäre 0, weis ich nicht :-(

Ja, es wird aus dem RAM geholt. Warum meinst du, dass es falsch wäre?
Deine Antwort klingt zumindest so.
Autor: Udo (Gast)
Datum:

Habe nochmal geschaut. An der Stelle steht wirklich 0x00 drin.
In dem Bereich liegt der Stack - ist also ein Stack Zugriff.

Greift der falsch auf den Stack zu? Ist schon komisch, da es nur ab und
zu dieses Verhalten bringt.
Autor: Udo (Gast)
Datum:

Weitere Erkenntniss:

der code oben ist der Assembler Code einer switch-case Anweisung.


switch (value):
 >> code_oben

case 0:
  break;

case 1:
  break;

...

case 7:
  break;

Wenn ich nur 4 case Auswertungen habe, 3 andere also weglösche, sieht
der ASM code anders aus (andere Befehlfolge). Und dann schmiert er auch
nicht ab.

Für den Compiler gilt also ab 5 case Auswertungen eine andere
Optimierung?


Desweiteren habe ich die switch-case durch ein if-else-if ersetzt.
Damit gehtn auch alle meine 7 erfolgreich - auch weil anderer ASM code
erzeugt wird.


Welche Gründe gibt es denn hierfür?
Autor: Johann L. (gjlayde) Benutzerseite
Datum:

Udo schrieb:
> Weitere Erkenntniss:
>
> der code oben ist der Assembler Code einer switch-case Anweisung.
>
>
> switch (value):
>  >> _code_oben_
>
> case 0:
>   break;
>
> case 1:
>   break;
>
> ...

Sieht den Code wirklich so aus?
also in etwa
int a;
void foo (int i)
{
    switch (i)
    {
        a = 1;
        
        case 2:
            a = 4;
            break;
            
        case 5:
            a = 7;
            break;
    }
}

Code im switch ohne case/default davor ist nicht wirklich prickelnd...

> Wenn ich nur 4 case Auswertungen habe, 3 andere also weglösche, sieht
> der ASM code anders aus (andere Befehlfolge). Und dann schmiert er auch
> nicht ab.
>
> Für den Compiler gilt also ab 5 case Auswertungen eine andere
> Optimierung?

Ja. Ab 5 oder 4 (hängt wiederum von was anderem ab) case-Labels
verwendet gcc Sprungtabellen, wenn die case-Werte "dicht" sind. Das
müsste in deinem Code erkennbar sein, indem zB der Startwert der
Sprungtabelle in ein Register geladen wird, etwas simple Arithmetimk
darauf veranstaltet wird und dann indirekt darüber gesprungen wird.

> Desweiteren habe ich die switch-case durch ein if-else-if ersetzt.
> Damit gehtn auch alle meine 7 erfolgreich - auch weil anderer ASM code
> erzeugt wird.
>
>
> Welche Gründe gibt es denn hierfür?

Denkbar ist ein Compilerfehler. Um den Fehler nachvollziehbar zu machen
empfiehlt sich ein Testfall, den andere übersetzen können. Hilfreich ist
dann eine möglichst einfache/kurze Quelle zu haben. Leider ist das nicht
immer möglich, wenn Änderungen "hier" einen Fehler "da" bewirken.

PPC-Code ist für mich absolutes Kauderwelsch :-) Die Quelle mit
-save-temps -dp -fverbose-asm zu übersetzen bringt aber lesbare
Kommentare in der .s Datei (evtl. -dP).
Autor: Udo (Gast)
Datum:

Also bei mir siehts so aus:

[c]
  switch(actionId)
  {
    case 0:
      foo0();
      break;
    case 1:
      foo1();
      break;
    case 2:
      foo2();
      break;
    case 3:
      foo3();
      break;
    case 4:
      foo4();
      break;
    case 5:
      foo5();
      break;
    case 6:
      foo6();
      break;
    case 7:

      break;
  }
[c]


Zwischen Switch und dem ersten case steht natürlich kein Code. Wollte
oben nur hindeuten dass an dieser Stelle der ASM von ganz oben steht.
Autor: Johann L. (gjlayde) Benutzerseite
Datum:

Ok. Dein compilierbarer Testfall ist also
void foo0();
void foo1();
void foo2();
void foo3();
void foo4();
void foo5();
void foo6();

void test (int actionId)
{
  switch (actionId)
  {
    case 0:  foo0();  break;
    case 1:  foo1();  break;
    case 2:  foo2();  break;
    case 3:  foo3();  break;
    case 4:  foo4();  break;
    case 5:  foo5();  break;
    case 6:  foo6();  break;
    case 7:
       break;
  }
}

für den falscher Code erzeugt wird -> Bugreport für gcc erstellen falls
der Fehler nicht schon bekannt ist. Ohne konkreten Code ist da aber
nix zu wollen, also Kommentare wie
// irgendein Code
werden vom Compiler wie Kommentare behandelt, es gibt keine Magie, die
deine C-Quelle rät :-)
Autor: TManiac (Gast)
Datum:

Hallo Udo,

Welchen Compiler nutzt du überhaupt? Es gibt nunmal für den PPC
haufenweise Compiler. Und ehrlich bezweifle ich dass ein Bug im Compiler
daran schuld ist.

Wie sieht dein Linkerfile aus? Ist das aufgeräumt? Eine Sprungtabelle
für switch anweisungen steht im Normalfall nicht im Stack oder RAM.
Sprünge mit Adrressen aus dem RAM kommen nur bei berechneten Adressen
vor, Also Zugriffen auf (größere) Arrays oder Strukturen. Sonderfall
sind natürlich Rücksprünge aus einer Unterfunktion.

Wenn du einen Debuger zur Verfügung hast, dann schau dir den Stack im
Programmablauf genau an. Wird der Stack überhaupt bis zu der Adresse
gefüllt? Wenn ja wann?

Hast du nur einen Stack oder mehrere? Bei nur einem würde es mich noch
mehr wundern wenn der Compiler eine Sprungadresse aus dem Stack
herauskramt. Vorallem wie in deinem Fall mit einer festkodierten
Arithmetik. Der Stack könnte je nach eingetroffener Interupte völlig
anders aussehen.

Wie gesagt, schau dir dein Linkerfile an. Wenn der Stack
(unbeabsichtigt) beeinflusst wird, ist das nicht lustig man sucht Tage
lang an den falschen Stellen nach Fehlern. Das hab ich erst letzte Woche
durch (war aber kein selbstgeschriebener Code).

Gruß,
TManiac
Autor: Lothar Miller (lkmiller) (Moderator) Benutzerseite
Datum:

Ich würde auf einen amoklaufenden Pointer tippen, der den Stack
zerhagelt. Du suchst vermutlich an der falschen Stelle. Aber mangels
konkretem Code lässt sich das nicht verifizieren...
Autor: Udo (Gast)
Datum:

Compiler ist Metrowerks 2.x. Habe zwei verschiedene Versionen probiert,
gleiches Verhalten. Ich denke eigentlich auch nicht dass es der Compiler
ist.

Benutze nur 1 Stack. Im Linkerfile ist dieser auch separat wie alle
andere Sektionen angegeben. Stack liegt als letztes im RAM.
SRAM geht von 0x4000.0000 bis 0x4004.0000.

Stack:
Adress            Length
0x4003.0000       0x0000.0FF0


STACK_START = ADDR(Stack)+LEN(Stack)
STACK_END = ADDR(Stack)


Ohje - amoklaufende Pointer. Da swill man nicht wirklich debuggen :-(
Autor: Karl L. (movex)
Datum:

Grundsätzlich erstmal die Fragen:

- treten Exceptions auf bzw. werden diese gezielt abgefagen ?
- sind Interrupts aktiviert ? (bei längeren Interruptroutinen
  reicht es nicht unbedingt aus die Register 0-12 zu sichern sondern
0-30)
- wird ein Codewarrior defaultprojekt verwendet oder modifizierte
Einstellungen (v.a. Linker file) ? (kann zur Folge haben das Variablen
nicht initialisiert werden, Stichwort: Rom Image bei den Linker
Einstellungen)

Um welches MPC56xx device handelt es sich ?
Evt. mal mit Book-E anstatt VLE compilieren.
Autor: Udo (Gast)
Datum:

- Exceptions treten nachweisbar keine auf. IVxR Register sind
programmiert.
- Interrupts sind an. Das mit den r0..r30 werde ich nachsehen, Danke!
- verwendet wird ein startup vom 55xx , sollte aber gehen. Linker File
ist selbst erstellt. Das alles da das Device sehr neu ist. Ist ein 567x,
mehr sollte ich denke ich nicht veröffentlichen.

BookE werde ich auch mal probieren.

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel




Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder GIF-Format hochladen.
Siehe Bildformate
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken erkennst du die Nutzungsbedingungen an.

webmaster@mikrocontroller.netImpressumNutzungsbedingungenWerbung auf Mikrocontroller.net