Ich möchte meinen Beitrag nochmal erweitern, da ich es jetzt verstanden habe. Hoffe ich zumindest.

Der ARM Kern arbeitet mit 32 Bit. Jeder Befehl belegt damit 4 Bytes.
Um eine 32 Bit Konstante in dem Befehl unterzubringen gibt es nicht genug Platz.
Der eigentliche Befehl (Mnemonic) benötigt ja schon einige Bits. Dann kommen noch Bits
für die Auswahl des Registers dazu usw. Also hat man hier einen besonderen Weg beschritten.
Die 32 Bit Konstante wird irgendwo im Speicher abgelegt und über einen Zeiger wird
darauf zugegriffen. Sie wird aber nicht direkt hinter dem momentanen Befehl abgelegt, daß
würde den Programmablauf stören, denn dann müste man über diesen Wert ja rüberspringen.
Also irgendwo dort, wo sie nicht stört. Zum Beispiel am Ende einer Unterfunktion.
Allzuweit jedoch darf der Wert auch wieder nicht stehen, da auf ihn mit einem Offset zum
momentanen Programmcounter zugegriffen wird.
Dieser Offset hat nur 12 Bit. Damit muss die Konstante innerhalb des momentanen 4-KByte Blockes stehen.
Also Plus Minus 2KByte vom aktuellen Programmcounter. Wo genau, legt der C-Compiler fest, da braucht
man sich nicht drum zu kümmern. Das sieht dann nur etwas verwirrend aus, wenn man sich das erste mal
den Assemblercode ansieht.

Beispiel:

unsigned long temp;
temp = 0x1FF;

Der resultierende Assembler-Code:

LDR R0,[PC,#+1632]
MOV R1,#0xFF
ORR R1,R1,0x0100
STR R1,[R0,#+0]

Erklärung:
Lade R0 Register mit der Adresse von Temp. Diese findest du an der momentanen Programmcounter Adresse + einem positiven Offset von 1632. Dort

wurde nämlich der 32 Bit Wert der RAM Adresse von Temp eingetragen. Dafür hat der C-Compiler gesorgt. Zum Beispiel 0x400005C4
Nun lade R1 Register mit dem Wert 0xFF. Es kann nicht direkt 0x1FF geladen werden. Erklärung folgt.
in R1 haben wir also vorerst den Wert 0xFF. Nun wird mit einem logischem OR der Rest von 0x1FF (also der vordere Teil 0x100) aufaddiert

(dazugepackt, oderiert). Wir haben nun also den Wer 0x1FF im R1 Register.
Jetzt wird der Wert welcher sich im R1 Register befindet an die Speicherstelle geschrieben, worauf
das Register R0 zeigt. Als Offset wird hier 0 angegeben, da R0 schon direkt auf die Speicheradresse von temp zeigt.

Soweit so gut, doch warum kann der Prozessor nicht gleich den Wert 0x1FF in sein Register R1 laden ?
Dazu muss man sich die Architectur bzw. den Adressmodus für den Befehl genauer ansehen.
Im Bit 0..7 des Befehls "MOV" ist Platz für eine 8 Bit Konstante. Also Werte von 0x00 bis 0xFF.
In Bit 8 bis 11 kann ein Wert zum Rotieren angegeben werden. Also 4 Bits für die Rotation.
Wobei hier beachtet werden muss. Man kann nur gradzahlig rotieren. Das bedeutet, die Rotation erfolgt um das doppelte,
als dieser 4 Bit Wert wiederspiegelt. Der höchste Wert, der in diese 4 Bits passt ist 15 also 0x0F. Das bedeutet
die 8 Bit Konstante in Bit 0..7 kann maximal um 30 Bits rotiert werden. Rotiert wird generell nach rechts.
Wichtig hierbei ist, daß "rotiert" wird, daß bedeutet die rechts "rausfallenden Bits" kommen links am oberen Ende
wieder an. Wenn also Bit 0 nach rechts rausgeschoben wird, kommt es an der Bitposition 31 wieder an.
Also kein Shift sondern Rotate. Bedingt durch diese Vorgegehensweise kann natürlich nicht jeder beliebige Wert als Konstante
dargestellt werden.

Genauere Information findet man im
ARM Achitecture Reference Manual , Juli 2005
ARM Adressing Modes
A5.1.3 Data-processing operands - Immediate

das war ja eine schwierige Geburt, aber man lernt nie aus.
Zumindest macht der Compiler keinen zusätzlichen Code, was meine erste Vermutung war.
Er nimmt einem die Prozessorbedingten Probleme (Eigenheiten) ab.
Damit kann ich jetzt beruhigt diesen Thread schließen.

mfg. Siro