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?
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?
> 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?
> 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.