Aller Anfang ist schwer.
Hallo,
ich arbeite mich gerade in GCCAVR ein und stoße auf zwei Fragen:
1. Bit-Copy:
Ich möchte nacheinander verschiedene Bits aus einer Variable in ein
IO-Register kopieren.
In ASM würde ich das so machen, wobei in r16 das auszugebende Byte
steht. Hier wird also erst das entsprechende Bit (6) gelöscht und dann,
wenn Bit 4 in r16 eins ist wieder gesetzt.
cbi PORTB, 6
sbrc r16, 4
sbi PORTB, 6
Wie schreibe ich so etwas in C, damit der Compiler daraus keine
unnötigen Befehle erzeugt?
2. Wenn ich inline assembly verwenden will, woher weiß ich, welche
Register ich dann frei verwenden kann?
3. Wo finde ich weitere Informationen darüber, wie man Daten zwischen C
Funktionen und Inline Assembly austauscht.
Danke,
Bernd
Bernd M. wrote:
> Wie schreibe ich so etwas in C, damit der Compiler daraus keine> unnötigen Befehle erzeugt?
if (x&(1<<4))
PORTB|=(1<<6);
else
PORTB&=~(1<<6);
> 2. Wenn ich inline assembly verwenden will, woher weiß ich, welche> Register ich dann frei verwenden kann?
Darum kümmert sich der Compiler. Dazu musst du ihm mitteilen, welche
Register du verwendest. Siehe Dokumentation. Ich würde dir aber
empfehlen erstmal kein inline asm zu verwenden, das ganze Zeug mit
inline asm ist meiner Meinung nach etwas dumm gemacht und sehr
fehleranfällig wenn man nicht ganz verstanden hat wie das genau
funktioniert.
> 3. Wo finde ich weitere Informationen darüber, wie man Daten zwischen C> Funktionen und Inline Assembly austauscht.
Dokumentation die beim Compiler dabei ist.
Mal abgesehen davon, dass die Funktion bei Bit4=0 5 Zyklen und by Bit4=1
6 Zylken braucht funktionniert es. Allerdings braucht die ASM variante
jeweils nur 5 Zyklen und besteht nur aus 3 Befehlen.
Die Frage ist allerdings, woher weiß ich, wenn ich Inline Assemble
programiere, in welchem Register der Compiler die Variable unterbring?
Ich weiß, die Doku, aber die ist meist nur schwer verständlich.
Grüße,
Bernd
48: if (b&(1<<4))
+0000007A: FF84 SBRS R24,4 Skip if bit in
register set
+0000007B: C002 RJMP PC+0x0003 Relative jump
49: PORTB|=(1<<6);
+0000007C: 9A2E SBI 0x05,6 Set bit in I/O
register
+0000007D: C001 RJMP PC+0x0002 Relative jump
51: PORTB&=~(1<<6);
+0000007E: 982E CBI 0x05,6 Clear bit in I/O
register
5
Bernd M. wrote:
> Mal abgesehen davon, dass die Funktion bei Bit4=0 5 Zyklen und by Bit4=1> 6 Zylken braucht funktionniert es. Allerdings braucht die ASM variante> jeweils nur 5 Zyklen und besteht nur aus 3 Befehlen.
Dann versuchs mal so:
PORTB&=~(1<<6);
if (x&(1<<4))
PORTB|=(1<<6);
Das müsste das gleiche wie die Assembler Lösung erzeugen.
> Die Frage ist allerdings, woher weiß ich, wenn ich Inline Assemble> programiere, in welchem Register der Compiler die Variable unterbring?
Das weist du nicht, denn der Compiler entscheidet das. Du sagst dem
Compiler, dass du den Wert der Variable x benötigt, die dann im
Assembler Coder den Platzhalter 0 bekommt, und du teilst dem Compiler
mit, dass du das Ergebnis deiner Berechnungen in y haben möchtest, die
dann den Platzhalter 1 bekommt.
Welche Register am Ende für 0 und 1 verwendet werden, entscheidet der
Compiler.
Dumme Frage, dann mir jemand einen Link mit Seitenangabe schicken, wo
das beschreiben ist. Ich weiß nämlich ehrlich gesagt nicht, wo ich
suchen soll.
Ich habe als Compiler das WinAVR Packet installiert. Da ist auch ein DOC
Folder, nur dann weiß ich nicht mehr weiter.
Bernd
Eine eigene Frage?
Dieser Thread ist über 19 Jahre alt.
Stell sie in einem eigenen Thread – dort lesen mehr Leute mit, und sie wird öfter und schneller beantwortet.