mikrocontroller.net

Forum: Compiler & IDEs Zugriff auf long long mit asm volatile


Autor: Schawwi (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo!

Ich möchte die Differenz zweier unsigned-short-Variablen möglichst 
schnell zu einer signed-long-long-Variable addieren. Da das Ergebnis der 
Differenz (lastadcvalue - zero) im Bereich von +/- 65536 liegt, reichen 
ja 3 Byte (lastadcvalue, tempA) für den Inhalt des Wertes aus. Ein 
weiteres Byte (tempB) nimmt dann die eventuellen Einsen des 
Zweierkomplements für vorstehende Bytes auf.

Mein dazu gehörender C-Code sieht so aus:
unsigned short us_temp;
asm volatile ( // rec_adcsum[rec_samplescounter] += (signed long long)rec_lastadcvalue - zero;
  "clr     %A[temp]                           \n\t"
  "clr     %B[temp]                           \n\t"
  "sub     %A[lastadcvalue], %A[zero]         \n\t"
  "sbc     %B[lastadcvalue], %B[zero]         \n\t"
  "sbc     %A[temp],         __zero_reg__     \n\t"
  "sbc     %B[temp],         __zero_reg__     \n\t"
  "add     %A[adcsum],       %A[lastadcvalue] \n\t"
  "adc     %B[adcsum],       %B[lastadcvalue] \n\t"
  "adc     %C[adcsum],       %A[temp]         \n\t"
  "adc     %D[adcsum],       %B[temp]         \n\t"
  "adc     %E[adcsum],       %B[temp]         \n\t"
  "adc     %F[adcsum],       %B[temp]         \n\t"
  "adc     %G[adcsum],       %B[temp]         \n\t"
  "adc     %H[adcsum],       %B[temp]             "
    : [adcsum] "+r" (rec_adcsum[rec_samplescounter]), [temp] "=&r" (us_temp)
    : [lastadcvalue] "r" (rec_lastadcvalue), [zero] "r" (zero)
);

Leider kommt der folgende Assembler-Code raus:
LDS     R30,0x05CA
CLR     R31       
LDI     R18,0x03  
LSL     R30       
ROL     R31       
DEC     R18       
BRNE    PC-0x03   
SUBI    R30,0x17  
SBCI    R31,0xFA  
LDS     R16,0x05E7
LDS     R17,0x05E8
LDS     R26,0x0104
LDS     R27,0x0105
LDD     R18,Z+0   
LDD     R19,Z+1   
LDD     R20,Z+2   
LDD     R21,Z+3   
LDD     R22,Z+4   
LDD     R23,Z+5   
LDD     R24,Z+6   
LDD     R25,Z+7   
MOVW    R28,R26   
CLR     R26       
CLR     R27       
SUB     R16,R28   
SBC     R17,R29   
SBC     R26,R1    
SBC     R27,R1    
ADD     R18,R16   
ADC     R19,R17   
ADC     R20,R26   
ADC     R21,R27   
ADC     R18,R27   
ADC     R18,R27   
ADC     R18,R27   
ADC     R18,R27   
STD     Z+0,R18   
STD     Z+1,R19   
STD     Z+2,R20   
STD     Z+3,R21   
STD     Z+4,R22   
STD     Z+5,R23   
STD     Z+6,R24   
STD     Z+7,R25   

Wie man sieht, funktioniert die Registerzuordnung der oberen 4 Byte der 
long-long-Variable mit den Buchstaben E bis H nicht, weil sie alle auf 
den A-Wert mit Register 18 zeigen. Kann man etwa keine 
long-long-Variablen in Inline-Assembler verwenden?

Danke für Antworten!

Christian

Autor: Falk Brunner (falk)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@ Schawwi (Gast)

>Ich möchte die Differenz zweier unsigned-short-Variablen möglichst
>schnell zu einer signed-long-long-Variable addieren.

Warum glaubst du das mit Inline Assembler machen zu müssen? SOOOO 
schlecht ist dein Compiler nicht.
Lass den Käse und schreibs einfach hin.
unsigned short a,b, tmp;
signed long long c;

tmp = (a-b);
c = c + tmp;

MfG
Falk

Autor: Schawwi (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Falk!

Ich finde schon, dass er das schlecht macht.
Die Sache ist, dass die Differenz größer sein kann als signed short. 
Demnach müsste ich hierfür signed long nehmen.

Also lautet mein C-Code:
signed long sl_temp;
sl_temp = rec_lastadcvalue - zero;
rec_adcsum[rec_samplescounter] = rec_adcsum[rec_samplescounter] + sl_temp;

Und der Assembler-Code wird deutlich länger als das, was bei meiner 
Variante nötig wäre.
LDS     R18,0x05E7
LDS     R19,0x05E8
LDS     R22,0x0104
LDS     R23,0x0105
LDS     R24,0x05CA
MOV     R6,R24    
CLR     R7        
LDS     R30,0x05CA
MOV     R26,R30   
CLR     R27       
LDI     R31,0x03  
LSL     R26       
ROL     R27       
DEC     R31       
BRNE    PC-0x03   
SUBI    R26,0x17  
SBCI    R27,0xFA  
LD      R24,X     
STD     Y+1,R24   
MOVW    R30,R26   
LDD     R31,Z+1   
STD     Y+2,R31   
MOVW    R30,R26   
LDD     R31,Z+2   
STD     Y+3,R31   
MOVW    R30,R26   
LDD     R31,Z+3   
STD     Y+4,R31   
MOVW    R30,R26   
LDD     R31,Z+4   
STD     Y+5,R31   
MOVW    R30,R26   
LDD     R31,Z+5   
STD     Y+6,R31   
MOVW    R30,R26   
LDD     R31,Z+6   
STD     Y+7,R31   
MOVW    R30,R26   
LDD     R26,Z+7   
STD     Y+8,R26   
SUB     R18,R22   
SBC     R19,R23   
CLR     R20       
CLR     R21       
MOVW    R26,R20   
MOVW    R24,R18   
LSL     R27       
SBC     R24,R24   
MOV     R25,R24   
MOVW    R26,R24   
STD     Y+9,R18   
STD     Y+10,R19  
STD     Y+11,R20  
STD     Y+12,R21  
STD     Y+13,R24  
STD     Y+14,R24  
STD     Y+15,R24  
STD     Y+16,R24  
LDD     R8,Y+1    
LDD     R31,Y+9   
ADD     R8,R31    
LDI     R24,0x01  
LDD     R25,Y+1   
CP      R8,R25    
BRCS    PC+0x02   
LDI     R24,0x00  
LDD     R9,Y+2    
LDD     R30,Y+10  
ADD     R9,R30    
LDI     R18,0x01  
LDD     R31,Y+2   
CP      R9,R31    
BRCS    PC+0x02   
LDI     R18,0x00  
ADD     R24,R9    
LDI     R25,0x01  
CP      R24,R9    
BRCS    PC+0x02   
LDI     R25,0x00  
OR      R18,R25   
MOV     R9,R24    
LDD     R10,Y+3   
LDD     R24,Y+11  
ADD     R10,R24   
LDI     R19,0x01  
LDD     R25,Y+3   
CP      R10,R25   
BRCS    PC+0x02   
LDI     R19,0x00  
MOV     R24,R18   
ADD     R24,R10   
LDI     R25,0x01  
CP      R24,R10   
BRCS    PC+0x02   
LDI     R25,0x00  
OR      R19,R25   
MOV     R10,R24   
LDD     R11,Y+4   
LDD     R30,Y+12  
ADD     R11,R30   
LDI     R18,0x01  
LDD     R31,Y+4   
CP      R11,R31   
BRCS    PC+0x02   
LDI     R18,0x00  
MOV     R24,R19   
ADD     R24,R11   
LDI     R25,0x01  
CP      R24,R11   
BRCS    PC+0x02   
LDI     R25,0x00  
OR      R18,R25   
MOV     R11,R24   
LDD     R12,Y+5   
LDD     R24,Y+13  
ADD     R12,R24   
LDI     R19,0x01  
LDD     R25,Y+5   
CP      R12,R25   
BRCS    PC+0x02   
LDI     R19,0x00  
MOV     R24,R18   
ADD     R24,R12   
LDI     R25,0x01  
CP      R24,R12   
BRCS    PC+0x02   
LDI     R25,0x00  
OR      R19,R25   
MOV     R12,R24   
LDD     R13,Y+6   
LDD     R30,Y+14  
ADD     R13,R30   
LDI     R18,0x01  
LDD     R31,Y+6   
CP      R13,R31   
BRCS    PC+0x02   
LDI     R18,0x00  
MOV     R24,R19   
ADD     R24,R13   
LDI     R25,0x01  
CP      R24,R13   
BRCS    PC+0x02   
LDI     R25,0x00  
OR      R18,R25   
MOV     R13,R24   
LDD     R14,Y+7   
LDD     R24,Y+15  
ADD     R14,R24   
LDI     R19,0x01  
LDD     R25,Y+7   
CP      R14,R25   
BRCS    PC+0x02   
LDI     R19,0x00  
MOV     R25,R18   
ADD     R25,R14   
LDI     R24,0x01  
CP      R25,R14   
BRCS    PC+0x02   
LDI     R24,0x00  
OR      R24,R19   
LDD     R15,Y+8   
LDD     R30,Y+16  
ADD     R15,R30   
ADD     R24,R15   
MOVW    R30,R6    
LDI     R23,0x03  
LSL     R30       
ROL     R31       
DEC     R23       
BRNE    PC-0x03   
SUBI    R30,0x17  
SBCI    R31,0xFA  
STD     Z+0,R8    
STD     Z+1,R9    
STD     Z+2,R10   
STD     Z+3,R11   
STD     Z+4,R12   
STD     Z+5,R13   
STD     Z+6,R25   
STD     Z+7,R24   

Grüße,

Christian

Autor: Falk Brunner (falk)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@ Schawwi (Gast)


>Ich finde schon, dass er das schlecht macht.
>Die Sache ist, dass die Differenz größer sein kann als signed short.
>Demnach müsste ich hierfür signed long nehmen.

Ja. Musst du aber auch in ASM (naja, man kann mit 24 Bit rechen, bringt 
aber nicht viel wenn es um die Summe mit long long geht, CARRY!).

>Also lautet mein C-Code:

>Und der Assembler-Code wird deutlich länger als das, was bei meiner
>Variante nötig wäre.

MOMENT! Das sind Indizierungen drin. Die werden dadurch nicht kürzer. 
Optimierung eingeschaltet? Denn ohne ist das reichlich sinnlos.

MFg
Falk

Autor: Schawwi (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Falk!

Doch, Optimierung ist an. Habe auch alle Stufen durchprobiert und von 
der Länge ändert sich auf einen groben Blick nichts.

Hast Du andere Ideen?

Grüße,

Christian

Autor: Falk Brunner (falk)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@ Schawwi (Gast)

>Doch, Optimierung ist an. Habe auch alle Stufen durchprobiert und von
>der Länge ändert sich auf einen groben Blick nichts.
>Hast Du andere Ideen?

Leider nein. So richtig sehe ich da nicht durch. Aber wie es scheint 
kann/will der GCC die Operanden nicht in den Registern halten (hat ja 
nur 32 Stück . . .) und läd immer über ldd nach. Wobei eine 8 + 8 Byte 
Addition nun wirklich nicht die Welt ist. :-(
Da musst du dich wohl oder übel mehr mit Inline Assembler rumschlagen. 
Aber vielleicht ist es besser, die Berechnug in eine Funktion 
auszulagern und richtig in Assembler zu programmieren. Das soll 
einfacher sein.

MFg
Falk

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.