Hallo NG, habe hier ein Problem. Einen Programmteil habe ich geschrieben. Der funktionier auch. Das selbe Assemblerkonstrukt eines compilierten C-Code funktioniert nicht. Aber warum? Dabei soll mal ausser acht gelassen werden, ob bei einer Routine solange gewartet wird, bis der Pin auf High / Low ist, und bei dem anderen vielleicht umgekehrt. Es sollte auf jeden Fall in beiden Versionen einen Zustand geben, in dem gewartet wird, bis sich der Zustand ändert. 1. Meine Version (geht): card_present: LDR r0, =PIO_BASE LDR r1, [r0, #PIO_PDSR] AND r1, r1, #BIT15 CMP r1, #BIT15 BNE card_present 2. Die Version aus dem C-Konstrukt vom Compiler (geht nicht) card_present: LDR r1, =PIO_BASE LDR r1, [r1, #PIO_PDSR] LSL r1, r1, #16 BMI card_present
Muss ich vielleicht irgend etwas beachten, um den BMI verwenden zu können? Hab echt keine Ahnung, warum das nicht funktioniert... LSL wäre doch der Befehl, der in Bsp2 den BMI beeinflusst, oder?
Also so wie ich das sehe, schiebt die Compiler-Version das zu prüfende Bit an bit31. Das sollte doch eigentlich das Bit für positiv- / negativ Zahlen sein, oder? Wieso zieht aber dann BMI nicht?
Habe jetzt mal zum Testen folgendes gemacht: card_present: LDR r1, =11111111111111111111111111111111b LSL r1, r1, #15 BMI card_present Meines Erachtens nach sollte da doch eine Endlosschleife herauskommen. Tut es aber nicht. Warum nur? Bit31 sollte doch auf jeden Fall "1" sein und somit N im Statusregister gesetzt. Ist es aber nicht. Was mache ich da blos falsch?
Verwendet den BMI denn niemand von euch?
Doch. Aber ich setze vorher das Sign-Bit. Du nicht. Tip: Die CMP-Befehle sind die einzigen ALU-Befehle, die immer die Statusbits setzen. Bei den übrigen ALU-Befehlen muss man das extra sagen.
@Andreas Kaiser zunächst mal Danke für Deine Antwort. Allerdings verstehe ich es nicht. Was muss ich vorher sagen, und wie? Es sollte doch auch ohne CMP funktionieren, nachdem es ja scheinbar auch der Compiler so macht (siehe Beispiel 2). Wäre echt nett, wenn Du noch einen konkreteren Satz darüber verlieren könntest... MfG Peter
> Was muss ich vorher sagen, und wie?
Das war nun die falsche Antwort. Ich hatte noch eine gewisse Hoffnung,
dass du doch mal das Handbuch absuchst, statt den einfachere Weg zu
gehen und zu fragen.
Es funktioniert mit LSL (eigentlich: MOV r, r, r, lsl #...) sehr wohl,
wenn man den Befehl auf die richtige Art angibt.
Danke für Deine Hilfe. Sorry, aber ich verstehe halt nicht, warum das so ist. Der Compiler erzeugt den Code aus Beispiel 2, nicht ich. Deshalb verstehe ich nicht, wie das überhaupt funktionieren soll, wenns nicht mal in der Simulation das N-Flag verändert. Hab heute in der früh auch noch kurz ein asl versucht. Aber der Assembler macht ein lsl daraus. Bin irgendwie verunsichert. Dachte, der Assembler "optimiert" nichts, und alles ist so, wie ich es eingebe... Wie kommt es, dass ich beim Debugen andere Befehle sehe, als die, die ich eingegeben habe? Also die Moral von der Geschichte ist dann, wenn ich Dich recht verstehe, dass es mit einem MOV r1, r1, r1, LSL #16 funktionieren sollte, das N-Flag zu setzen, oder?
> Also die Moral von der Geschichte ist dann, wenn ich Dich recht > verstehe, dass es mit einem MOV r1, r1, r1, LSL #16 funktionieren > sollte, das N-Flag zu setzen, oder? Nein. Sondern mit MOVS.
Vielen Dank! Werd ich heute abend gleich mal ausprobieren. Hast Du vielleicht eine Idee, was das Problem mit dem Compiler betrifft, dass er zum einen den Code aus Bsp2 (von C) erzeugt und zum anderen scheinbar meine ASM-Befehle "optimiert"?
Also fürs Protokoll: mit MOVS r1, r1, LSL #16 wird das N-Flag richtigerweise gesetzt. Alles Super! Allerdings würde mich trotzdem noch interessieren, warum der IAR- Compiler aus: // ---------------------------------------------------------- // (C-Code): // ---------------------------------------------------------- // CP - card present while(((m_pPio->PIO_PDSR) & BIT15)) { /*put your card present event here*/ } // ---------------------------------------------------------- // das hier macht (ASM): // ---------------------------------------------------------- Next label is a Thumb label // while(((m_pPio->PIO_PDSR) & BIT15)) { /*put your card present event here*/ } 00000116 4823 LDR R0, [PC,#0x08C] ; [0x1A4] =m_pPio (0x694) 00000118 6800 LDR R0, [R0, #0] 0000011A 6BC0 LDR R0, [R0, #60] 0000011C 0400 LSL R0, R0, #16 0000011E D4FA BMI 0x000116 // ---------------------------------------------------------- Das kann doch so dann nie funktionieren, wenn das N-Flag nicht mit LSL gesetzt wird. Kann da nicht jemand Licht ins Dunkle bringen? Ist doch ne berechtigte Frage, oder?
Jetzt wird's klarer. Ich hatte mich schon länger über den Befehl LSL gewundert, denn genau genommen gibt's den im ARM Befehlssatz garnicht. Im Thumb Befehlssatz schon. ARM: Ob die Flags gesetzt werden oder nicht entscheidet das "S" hinten am Befehl (=> Bit im Opcode), ausser bei CMP/CMN (ergibt ohne irgenwie wenig Sinn). Thumb: Ob die Flags gesetzt werden oder nicht entscheidet die Befehlsreferenz. Nicht immer leicht zu durchschauen, weil sich ADD und ADD da unterscheiden. All das lässt sich übrigens prima selber feststellen, wenn man mal das ARM ARM von vorne bis ungefähr zu Mitte durchliest und dabei nicht vergisst, die grauen Zellen zu aktivieren.
Hallo Andreas nochmal, das ist schön, dass es für Dich jetzt klarer ist. Mir leuchtet das jetzt auch ein, dass das "S" angibt, dass die Flags gesetzt werden sollen. Leider verstehe ich nicht, warum der Compiler Code erzeugt, der so wie er ist nicht lauffähig ist. Zumindest denke ich das, weil in der Step-by-Step Simulation läuft es nicht so, wie es laufen sollte. Warum ist bei dem Board diese DEMO zu SD/MMC dabei, die man wunderbar in der IAR-Workbench öffnen kann, aber leider scheinbar keine brauchbare Binary erzeugt? Es ist nicht so, dass ich nicht lernfähig, oder willig wäre, aber irgendwo ist man halt immer mal auf Hilfe angewiesen, wenn was nicht so funktioniert, wie man es gerne hätte. Zugegeben, wahrscheinlich könnte man länger schauen, und nach Fehlern suchen. Aber brauchbare Beispiele sollten halt schon vorhanden sein. Weil nur Theorie ohne Praxis ist - für mich zumindest - hartes Brot :-( Wenn ich mir ein Buch kaufe, stehen dort doch auch viele praxisbezogene Beispiele drinnen. Das bringt mir persönlich mehr. Aber da ist jeder bestimmt ein bisschen anders veranlagt. Mich würde es auf jeden Fall sehr freuen, wenn die Frage zum Compiler-Code noch so geklärt werden könnte, dass auch ich es verstehe :-)
Was bringt dich zur Vermutung, dass der Compiler falschen Code erzeugt? Der im Posting von 20:25 wird so m.E. funktionieren. Zeig mir bitte mal die Variante, die nicht funktioniert. Aber als Assembler-Listing mit Hex-Code drin, nicht nur den Quellcode.
Ok. habe jetzt das ganze nochmals getestet. Es scheint im Thumbmode echt zu funktionieren :-) Mein Problem ist folgendes: Habe den C-Quelltext assemblieren lassen. Den erzeugte Assembler-Code habe ich dann in ein anderes Assembler-Projekt versucht eingefügt. An dieser Stelle macht der Assembler scheinbar keinen Thumb-Code mehr. Beispiel: aus: LSL R0, R0, #16 wird: 00000004 E1A00800 MOV R0, R0, LSL #16 Muss ich beim Programmieren im Quelltext irgendwo vermerken, dass ab einer bestimmten Stelle Thumb-Code kommt. Wenn ja - wie jann man das umstellen?
Hier nix IAR, da kann ich nicht weiterhelfen.
Ja, aber vielleicht komm ich ja drauf, wenn Du mir einfach sagst, wie es bei Dir funktioniert, ARM- und ThumbCode zu mischen. Vielen Dank!
Hallo NG, habe wohl soeben geschafft, dass der Proz/Emulator in den Thumb-Mode springt. Ist das mit dem BX wirklich immer nötig, oder gibts auch noch andere Methoden, um zwischen den Modes zu switchen? Es wird auch tatsächlich das N-Flag gesetzt, wenn das Bit1 nach Bit31 gewandert ist... main ADR R0, Into_THUMB BX R0 CODE16 Into_THUMB MOV r0, #1 LSL r0, r0, #1 LSL r0, r0, #1 LSL r0, r0, #1 LSL r0, r0, #1 LSL r0, r0, #1 LSL r0, r0, #1 LSL r0, r0, #1 LSL r0, r0, #1 LSL r0, r0, #1 LSL r0, r0, #1 LSL r0, r0, #1 LSL r0, r0, #1 LSL r0, r0, #1 LSL r0, r0, #1 LSL r0, r0, #1 LSL r0, r0, #1 LSL r0, r0, #1 LSL r0, r0, #1 LSL r0, r0, #1 LSL r0, r0, #1 LSL r0, r0, #1 LSL r0, r0, #1 LSL r0, r0, #1 LSL r0, r0, #1 LSL r0, r0, #1 LSL r0, r0, #1 LSL r0, r0, #1 LSL r0, r0, #1 LSL r0, r0, #1 LSL r0, r0, #1 LSL r0, r0, #1 LSL r0, r0, #1
> Ist das mit dem BX wirklich immer nötig, Wenn mit ARM7 (ARMv4) sowohl ARM- als auch Thumb-Code verwendet wird ja. ARM9 (ARMv5) wurde etwas erweitert, um die Nachteile, die durch durch dieses sogenannte "interworking" entstehen zu reduzieren.
Erst ARM9E ist ARMv5, ARM9 ist wie ARM7 ARMv4. Das bedeutet dass z.B. der weit verbreitete AT91RM9200 ARMv4 ist (ARM920T Kern), während dessen Nachfolger, die AT91SAM926x Reihe, ARMv5 (ARM926EJ-S Kern) ist.
Ok, vielen Dank für eure Antworten. Um dieses Thema mal langsam zu schließen, hätte ich noch eine abschließende Frage: Es sollte doch möglich sein, dem C-Compiler zu sagen, dass er keinen 16Bit-Thumb-Code erzeugen soll, sondern 32Bit-ARM-Code, oder?
Habs eben selber gefunden: Projekt -> Options -> General Options -> Processor mode -> (x) Arm
> Projekt -> Options -> General Options -> Processor mode -> (x) Arm
Wird halt langsamer dadurch, jedenfalls bei Atmels SAM7 im Flash bei
voller Taktfrequenz, weil Atmels Flash zu schmalbandig ist. Durchsatz
ist effektiv nur 16bit pro Takt.
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.