While-Loop-Anweisungen in der Bildzerlegung nicht klar

Um Platz zu sparen versuche ich den generierten C-Code mit inline asm(""); Wenn ich mir die ursprüngliche Disassemblierung und den gut funktionierenden Code ansehe, verstehe ich die Zeile 0x17E4 nicht.

void MENU_BUTTON(uchar Parm){

    // This loop ends when the enter key is pressed
    while EnterOpen(){                 // SW3 = RE2

       if ArrowUpClosed(){             //    RE0 
           while ArrowUpClosed(){};
            asm("call MBD");
            if ArrowUpOpen()       
                  LCDGotoPos(ArrowUp[index]);
        };
        if ArrowDownClosed(){          // SW3 RE1
            while ArrowDownClosed(){};
            asm("call MBD");
            if ArrowDownOpen()
                 LCDGotoPos(ArrowDown[index]);
        };
        if ArrowRightClosed(){          // SW4 RC1
            while ArrowRightClosed(){};
            asm("call MBD");
            if ArrowRightOpen()
                   LCDGotoPos(ArrowRight[index]);
        };
        if ArrowLeftClosed(){           // SW5 RC0
            while ArrowLeftClosed(){};
            asm("call MBD");
            if ArrowLeftOpen()
                   LCDGotoPos(ArrowLeft[index]);
        };
    };
    Pause(300);
    return;
    // a little trick to save space
    asm("MBD:");
    delay();
}; // End of MenuButtons.


    // This loop ends when the enter key is pressed
    while EnterOpen(){                 // RE2
    0x178E: BCF STATUS, 0x5
    0x178F: BCF STATUS, 0x6
    0x1790: BTFSS PORTE, 0x2
    // jumping out of the loop as expected
    0x1791: GOTO 0x7E5    
    // returns to the beginning? but during execution goes to 0x1792.
    // The way I expect
    0x17E4: GOTO 0x78E                 
    // during execution 
    //if ArrowUpClosed()             //   RE0 
    0x1792: BTFSC PORTE, 0x0

    //other code
    } // end of while EnterOpen

    //    Pause(300);
    0x17E5: MOVLW 0x8
Das ist Demontage. Wie lautet der ursprüngliche Assemblercode (und haben Sie ihn)?
Ähm, ist es nur die Reihenfolge der Zeilen, die falsch ist? Ich meine, 0x1792 sollte vor 0x17e4 stehen. Und Ihre Frage ist etwas schwer zu verstehen, da es Kommentare gibt, die Teil der Frage und Kommentare für alten Code sind (glaube ich?).
Ich habe den kompletten C-Code der Routine hinzugefügt. Der Disassemblierungscode stammt aus dem C-Code
Nach der Feststellung von @Arsenal würde ich die Qualität der Zerlegungsausgabe in Frage stellen. In seiner Ausgabe hat es eine Sequenz von 0x1791, dann 0x17E4 und dann 0x1792. Die mittlere Position, 0x17E4, liegt außerhalb der Programmzählersequenz.
Mittlerweile stimme ich Anonymous zu. Ich habe die Befehlsführung auf mein Wissen und Datenblatt umgestellt und die Routine funktioniert auch in asm
Wie von Jonk angegeben, ist 0x17E4 korrekt. Diese Anweisung wird jedoch übersprungen. Nicht klar warum.? Das Programm fährt wie vorgesehen bei 0x1792 fort.

Antworten (1)

Vorbehalte: Es ist mehr als ein Jahrzehnt her, dass ich routinemäßig PIC-Assembler-Code geschrieben habe (und ihren C-Compiler verwendet habe – ich bin mir auch nicht sicher, ob meine Lizenz noch gut ist.) Sie haben auch nicht gesagt, welchen Compiler Sie verwenden, also Ich kann mir keine Kopie besorgen und sehen, was sie erzeugt. Und ich weiß nicht einmal, ob Sie einen PIC16 oder einen PIC18 verwenden (andere Kreaturen, wobei der PIC18 schönere Vorkehrungen für den Assemblercode hat). Schließlich gehe ich davon aus, dass Sie mit dem PIC und dem in einigen ziemlich gut vertraut sind Wegen Ihrer aktuellen Arbeit im Vergleich zu meinem jahrzehntealten (und mehr) Wissen darüber werden Sie besser als ich in der Lage sein, spezifische Fragen zum Assemblercode zu beantworten.

Annahmen:

  1. Es ist ein PIC16 (oder niedrigeres) Familienteil und kein PIC18.
  2. Wenn Sie in Assembler-Code schreiben, verwenden Sie einen echten Assembler und keinen manuell codierten Maschinencode.
  3. Sie haben sich den generierten Maschinencode nicht genau angesehen.
  4. Sie sind unausgesprochene Verwirrung über die Adresse dort.

Unter der Annahme, dass das Obige richtig ist, vermute ich, dass Sie möglicherweise nicht bemerkt haben, dass die GOTO-Anweisung nur 11 Bits für die Adresse verwendet. Es kann nur innerhalb der aktuellen Code-"Page" verzweigt werden, wobei die oberen Adreßbits bei der Verzweigung zu einer neuen Adresse unverändert bleiben.

Wenn Sie in Assembly schreiben, verwenden Sie normalerweise Labels. Selbst wenn Sie absolute Adressen verwendet haben, "rechnet" der Assembler immer noch für Sie, um sicherzustellen, dass die von Ihnen angegebene Adresse "in Reichweite" ist. Sie würden also auf die eine oder andere Weise nicht einmal wissen, was vor sich geht, es sei denn, Sie sehen sich den von ihm generierten Maschinencode genau an.

Lassen Sie mich dokumentieren, was ich oben sehe (zusammen mit einer fehlenden Spalte, von der ich aufrichtig wünschte, Sie hätten sie auch aufgenommen):

Address    Machine Code    Code Lines             Description
0x178E                     BCF STATUS, 0x5        These two lines make sure that data access
0x178F                     BCF STATUS, 0x6            is on page 0 where PORTE is at.
0x1790                     BTFSS PORTE, 0x2       Skip GOTO if the loop should continue.
0x1791                     GOTO 0x7E5             Go out of loop to 0x17E5 (past the GOTO.)
0x1792                     BTFSC PORTE, 0x0       "if ArrowUpClosed()"
0x1793                                            <>
0x1794                                            <>
  ...                                             ...
0x17E1                                            <>
0x17E2                                            <>
0x17E3                                            <>
0x17E4                     GOTO 0x78E             Branch to address 0x178E (start of loop.)
0x17E5                     MOVLW 0x8

Wenn Sie feststellen, dass der codierte Maschinenbefehl für das GOTO nur 11 Bits enthält, können Sie sehen, warum nicht das gesamte „0x17E5“ oder „0x178E“ in das Maschinenwort codiert werden kann. Diese Tatsache hindert den Assembler und/oder Compiler jedoch nicht daran zu wissen, dass die Adresse tatsächlich richtig erreicht werden kann (oder nicht, was darauf hinweist, dass möglicherweise mehr Code benötigt wird, um eine weiter entfernte Übertragung durchzuführen.)

Der Code des Compilers funktioniert, glaube ich, sagen Sie. Sie sagen auch, dass es auch funktioniert hat, als Sie einen eigenen Assemblercode geschrieben haben. Ich glaube, beides ist wahr. Aber das Problem kann einfach sein, dass Sie nicht verstanden haben, wie ein Assembler (noch wichtiger, wie ein Linker) im Inneren arbeitet, um korrekten Code zu generieren oder Fehler zu generieren.

Der Assembler und der C-Compiler generieren eine Objektdatei, die "Strings" von wörtlichen Bytewerten + periodische "Patch-up"-Datensätze enthält, die den Linker genau anweisen, wo und wie er Bits und Teile dieser wörtlichen Strings währenddessen reparieren soll die Verlinkungsphase, wenn der Code tatsächlich irgendwo platziert wird. Ich bin mir ziemlich sicher, dass dies für Assembly-generierten Code ein sehr einfacher Prozess ist und der Linker sich beschweren wird, wenn Sie Anweisungen schreiben, die eine Codierung außerhalb des Bereichs erfordern würden. Beim C-Compiler bin ich mir nicht so sicher über die Komplexität, die sich auf den Linker ausdehnt. Aber es ist möglich, dass der C-Compiler nicht


Ich habe mich dazu geäußert. Es kann sein, dass ich Ihre Zwickmühle hier völlig missverstanden habe. Ich bin gerade aufgewacht und wer weiß, ob ich da nur im Schlaf wandle. Aber da ist es. Vielleicht könntest du das Gerät etc. auch klären?


Für diejenigen, die an etwas Geschichte über den XC8 C-Compiler sowie an Informationen über die Optimierungsunterschiede in den PRO-Versionen interessiert sind, fand ich diesen Link sofort nützlich. Daraus kann ich ersehen, dass der XC8-Compiler im Grunde der Hi-Tech-Compiler-Code ist, mit zusätzlichen "Beeinträchtigungen", um die Motivation zum Kauf der PRO-Version ihres Compiler-Toolsets zu "verbessern". Interessante Details dabei.

Das Gerät ist ein pic16F877A. Programmierung erfolgt mit XC8-Compiler. Ich war nicht verwirrt von den 11 Bits, die für GOTO benötigt werden. Das GOTO 0x78E scheint übersprungen zu werden (nicht klar, warum?), da das Programm bei 0x1792 fortfährt, wie es sollte.
@Decapod Ich bin verwirrt über deine Verwirrung. Das BTFSS überspringt das folgende GOTO, wenn die Schleife ausgeführt werden soll. Es überspringt GOTO nicht , wenn die Schleife nicht ausgeführt werden soll. Das ergibt für mich absolut Sinn. Sie kehren bei Bedarf einfach den Sinn des BTFSS/C-Tests um. Das GOTO unmittelbar nach dem BTFSS ist die Art und Weise, wie die Schleife beendet wird, weshalb sie sich nach diesem letzten GOTO verzweigt.
Oh oh. Ich muss geschlafen haben. Das Verstehen der Funktion und Funktionalität und dann das Überwachen dieser Situation, die dazu führt. Wo waren meine Gehirne. Verzeihung!! Konzentrieren Sie sich darauf, den Code zu reduzieren, denke ich. Inzwischen habe ich herausgefunden, dass die Codefresser die Lookup-Tables sind. Ein direkter Ansatz in asm mit retw spart viel Platz.
@Decapod Das BTFSS/C-Befehlspaar ist ein SEHR LEISTUNGSFÄHIGES Werkzeug zur Reduzierung der Codegröße. Ich habe viel Zeit damit verbracht, Assembler für die Familien PIC10, PIC12, PIC14, PIC16 und PIC18 zu schreiben, und es gab unzählige Situationen, in denen der Compiler nicht einmal ansatzweise sehen konnte, wo diese Anweisungen unzählige Zyklen und Befehlszeilen eingespart haben. Gehen Sie NICHT davon aus, dass sie nur GOTO-Anweisungen überspringen. Sie sind für viele andere Dinge nützlich. Ich habe sie sogar Rücken an Rücken verwendet, wobei einer den anderen für eine ziemlich nützliche, komplexe Logik übersprungen hat.
Ich habe das auch entdeckt und fand ihre Nützlichkeit in anderen Teilen des Programms.
@Decapod Eines Tages muss ich mich wieder in ihre Compiler-Toolchain einkaufen oder eine der kostenlosen Versionen erhalten. Basiert der XC8-Compiler auf der Compiler-Toolchain von GNU? Wenn dies der Fall ist, müssen sie den Compiler-Quellcode (alles) bereitstellen. Sie müssen natürlich nicht ihre Bibliotheken bereitstellen. Hast du irgendwelche Infos dazu?
XC8 ist die kostenlose Version
@Decapod Aber schränken sie die Compiler-Optimierungen ein? Wenn ja, und wenn es auf GNU angewiesen ist, können Sie das vollständig umgehen, da sie ihren gesamten Quellcode einschließlich des gesamten Optimierungscodes bereitstellen müssen und das Ganze mit den Quellen und ohne die Einschränkungen neu erstellt werden kann. ... Egal. Es ist der Hi-Tech-Compiler, den sie gekauft und dann „ein bisschen beschädigt“ haben.