PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Hilfe zu Bitoperationen in WINAVR



-tomas-
04.06.2006, 23:34
Ich hatte mal Code von Bascom nach WinAVR übertragen. https://www.roboternetz.de/phpBB2/viewtopic.php?t=20209

Bei den einfachen WINAVR-Bitoperationen hatte ich hiermit noch kein Problem:

Command_rc5.7 = Ir_data_tmp.5

Command_rc5 |= ( (Ir_data_tmp & (1<<5)) <<2 );

Nur wie übertragt man folgendes nach C?

Command_rc5.6 = Not Ir_data_tmp.6

Ich habe nur den Workaround gefunden:

if ((Ir_data_tmp & (1<<6))==0) Command_rc5 |= (1<<6);

PicNick
05.06.2006, 10:10
Da hast da das Übertragen von NULL nicht dabei, nur eine EINS.
Würde ich erstmal ganz einfach machen:


if (Ir_data_tmp & (1<<5)) command_rc5 |= (1<<7)
else command_rc5 &= ~(1<<7)

das zweite Beispiel analog.

-tomas-
05.06.2006, 16:47
Das mit der NULL ist mir entgangen :-(

Man scheint aber um eine IF ... ELSE und SHIFT nicht herum zukommen.

Das ist irgendwie eine Lücke in WinAVR-C, da der µC in ASM mit SBIC/SBIS und SBI/CBI diese o.g. Bitoperationen direkt unterstützt.

PicNick
05.06.2006, 17:44
Es ginge schon (scheinbar) mit bit-structuren. Es kommt aber der gleiche Code raus.
SBIC etc. bringt auch nur was, wenn es sich bei den Bitnummern um Literale handelt. Mit Variablen zur Laufzeit ist da auch nix.

SprinterSB
05.06.2006, 22:16
Wo ist da eine "Lücke" in C? :-k
Ist vielleicht etwas umständlich hinzuschreiben, dafür bleibt man bei den Standards:

extern uint8_t command_rc5, Ir_data_tmp;

void foo()
{
if (Ir_data_tmp & (1<<5))
command_rc5 |= (1<<7);
else
command_rc5 &= ~(1<<7);
}


Sieht doch gut aus, was avr-gcc daraus macht, oder?! sbic/sbis sind eh nur auf einige SFRs anwendbar...

foo:
lds r24,Ir_data_tmp
lds r25,command_rc5
sbrs r24,5
rjmp .L5
ori r25,lo8(-128)
rjmp .L7
.L5:
andi r25,lo8(127)
.L7:
sts command_rc5,r25
ret


Und falls das immer noch zu lange ist:

void foo()
{
uint8_t cmd = command_rc5 & ~(1<<7);

if (Ir_data_tmp & (1<<5))
cmd |= (1<<7);

command_rc5 = cmd;
}


gibt:

foo:
lds r25,command_rc5
andi r25,lo8(127)
lds r24,Ir_data_tmp
sbrc r24,5
ori r25,lo8(-128)
.L5:
sts command_rc5,r25
ret
Kürzer oder schneller schreibt das niemand.

-tomas-
06.06.2006, 10:19
Absolut überzeugend!

@SprinterSB
Womit erzeugt Du diesen ASM-Code (Labels, Variablen-Namen etc)?
AVRStudio erzeugt bei mir auch mit der *.elf nur RAW-ASM...

SprinterSB
06.06.2006, 12:11
Den Assembler-Code erzeuge ich mit avr-gcc. avr-gcc erzeugt immer Assembler-Code (zumindest, wenn er compiliert). Du darft ihn eben nicht löschen ;-)

(Als Option hilf dazu -save-temps. Leider bekomme ich dann teilweise Linkerfehler zusammen mit -c, die ich noch nicht nachvollziehen konnte; die Objekte scheinen jedoch gleich auszusehen...)

Generell kannst du auf 2 Wegen an den Assembler-Code kommen:
Indem man die Temporär-Dateien nicht löscht (gcc -save-temps), indem man nicht assembliert/linkt (gcc -S) oder indem man assembliert und dem Assembler sagt, daß er bitte dumpen soll. (avr-gcc -Wa,...).

Weiterhin kann man Disassembles erzeugen aus den Objekten (*.o, *.elf), indem man einen Dump macht oder den Linker anweist, es zu tun.

Welches man bevorzugt ist davon abhängig, welche Informationen man will: Intermix zwischen Assembler/C-Quelle? Maschinen-Codes zu den Assembler-Befehlen? Symbolnamen? Variablennamen? etc.

Für obiges Beispiel sieht das dann so aus:

Compiler dumpt Assembler
avr-gcc -S -save-temps -fverbose-asm ...

.global foo
.type foo, @function
foo:
/* prologue: frame size=0 */
/* prologue end (size=0) */
lds r25,command_rc5 ; cmd, command_rc5
andi r25,lo8(127) ; cmd,
lds r24,Ir_data_tmp ; Ir_data_tmp, Ir_data_tmp
sbrc r24,5 ; Ir_data_tmp,
ori r25,lo8(-128) ; cmd,
.L2:
sts command_rc5,r25 ; command_rc5, cmd
/* epilogue: frame size=0 */
ret
/* epilogue end (size=1) */
/* function foo size 11 (10) */
.size foo, .-foo


Assembler dumpt Assembler
avr-gcc -c -Wa,-alhd=dump.s ...

18 .global foo
20 foo:
21 .LFB2:
22 .LM1:
23 /* prologue: frame size=0 */
24 /* prologue end (size=0) */
25 .LM2:
26 0000 9091 0000 lds r25,command_rc5
27 0004 9F77 andi r25,lo8(127)
28 .LM3:
29 0006 8091 0000 lds r24,Ir_data_tmp
30 000a 85FD sbrc r24,5
31 .LM4:
32 000c 9068 ori r25,lo8(-128)
33 .L2:
34 .LM5:
35 000e 9093 0000 sts command_rc5,r25
36 /* epilogue: frame size=0 */
37 0012 0895 ret
38 /* epilogue end (size=1) */
39 /* function foo size 11 (10) */


objdump erzeugt Dump aus Object (nicht loakatiert):
avr-objdump -d -S ...

00000000 <foo>:
uint8_t command_rc5, Ir_data_tmp;

void foo()
{
uint8_t cmd = command_rc5 & ~(1<<7);
0: 90 91 00 00 lds r25, 0x0000
4: 9f 77 andi r25, 0x7F ; 127

if (Ir_data_tmp & (1<<5))
6: 80 91 00 00 lds r24, 0x0000
a: 85 fd sbrc r24, 5
cmd |= (1<<7);
c: 90 68 ori r25, 0x80 ; 128

command_rc5 = cmd;
e: 90 93 00 00 sts 0x0000, r25
12: 08 95 ret


objdump erzeugt dump aus elf (lokatiert)
avr-objdump -S ...

0000005c <foo>:
uint8_t command_rc5, Ir_data_tmp;

void foo()
{
uint8_t cmd = command_rc5 & ~(1<<7);
5c: 90 91 60 00 lds r25, 0x0060
60: 9f 77 andi r25, 0x7F ; 127

if (Ir_data_tmp & (1<<5))
62: 80 91 61 00 lds r24, 0x0061
66: 85 fd sbrc r24, 5
cmd |= (1<<7);
68: 90 68 ori r25, 0x80 ; 128

command_rc5 = cmd;
6a: 90 93 60 00 sts 0x0060, r25
6e: 08 95 ret

-tomas-
06.06.2006, 12:42
was für eine Antwort O:)

Ich schlage vor, es in Deinem Artikel einzupflegen:
https://www.roboternetz.de/wissen/index.php/Avr-gcc

SprinterSB
06.06.2006, 15:17
Na, der Artikel ist eh schon arg fett...

izaseba
06.06.2006, 17:52
Na, der Artikel ist eh schon arg fett...

Hallo Sprinter,
Das Problem ist, dieser Post geht schnell in der Menge unter, wenn man es später nachschauen will, ist man am suchen, es wäre wirklich schön, wenn Du das ins Wiki aufnehmen könntest [-o< .

Gruß Sebastian

P.S.
Zur Sicherheit habe ich mir alles kopiert :-)

SprinterSB
07.06.2006, 08:58
Ist schon da:
https://www.roboternetz.de/wissen/index.php/Assembler-Dump_erstellen_mit_avr-gcc

izaseba
07.06.2006, 17:09
Super danke :-)

Gruß Sebastian