mikrocontroller.net

Forum: Compiler & IDEs GCC - ATmega88: Berechnung von Konstanten zur compile-time


Autor: Bernd M. (bernd_m)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Forum,

ich habe gerade mit erstaunen festgestellt, dass der GCC konstante
Ausdrücke wie tmp = (18.6 * 10) nicht zur compile-time berechnet,
sondern die floating point Routinen zur run-time bemüht, was zu einem
erheblichen Mehr an Code und Rechenzeit führt.

Ich hatte erwartet, dass daraus ein simples tmp = 186 wird.

Gibt es eine Möglichkeit den GCC dazu zubringen konstante Ausdrücke zur
compile-time zu berechnen? Welchen switch habe ich übersehen?

Vielen Dank

Bernd

Autor: Andreas Schwarz (andreas) (Admin) Benutzerseite Flattr this
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Das tut der GCC mit Sicherheit. Allerdings wird daraus nicht 186,
sondern 186.0 (Float), das könnte der Grund für das beobachtete
Verhalten sein.

Autor: Nico Schümann (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Das sollte sich aber mit
tmp = (int)(18.6 * 10)
beheben lassen

Autor: Andreas Schwarz (andreas) (Admin) Benutzerseite Flattr this
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Bei einer einfachen Zuweisung sollte das der Compiler selbst erkennen,
das Problem dürfte eigentlich nur bei Ausdrücken mit Variablen
auftreten:

x = x * (18.6 * 10);

Autor: Rolf Magnus (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> ich habe gerade mit erstaunen festgestellt, dass der GCC konstante
> Ausdrücke wie tmp = (18.6 * 10) nicht zur compile-time berechnet,
> sondern die floating point Routinen zur run-time bemüht, was zu
> einem erheblichen Mehr an Code und Rechenzeit führt.

Kannst du mal den exakten Code zeigen?

Bei mir:

$ cat constant.c
int main()
{
    volatile float tmp = (18.6 * 10);
}
$ avr-gcc constant.c -S -o- -mmcu=atmega48
        .file   "constant.c"
        .arch atmega48
_SREG_ = 0x3f
_SP_H_ = 0x3e
_SP_L_ = 0x3d
_tmp_reg_ = 0
_zero_reg_ = 1
        .global __do_copy_data
        .global __do_clear_bss
        .text
.global main
        .type   main, @function
main:
/* prologue: frame size=4 */
        ldi r28,lo8(__stack - 4)
        ldi r29,hi8(__stack - 4)
        out _SP_H_,r29
        out _SP_L_,r28
/* prologue end (size=4) */
        ldi r24,lo8(0x433a0000)
        ldi r25,hi8(0x433a0000)
        ldi r26,hlo8(0x433a0000)
        ldi r27,hhi8(0x433a0000)
        std Y+1,r24
        std Y+2,r25
        std Y+3,r26
        std Y+4,r27
/* epilogue: frame size=4 */
        rjmp exit
/* epilogue end (size=1) */
/* function main size 13 (8) */
        .size   main, .-main
/* File "constant.c": code   13 = 0x000d (   8), prologues   4,
epilogues   1 */

Wie man unschwer erkennen kann, wird die Berechnung im Compiler
durchgeführt.

Autor: Bernd M. (bernd_m)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Vielen Dank für die Hinweise, habe die Problematik erkannt.

Die entscheidenden Hinweise kamen von Nico und Andreas.
Das Problem ist die Verwendung von Float multipliziert mit einer
integer Variablen. Die Multiplikation mit der Variablen hatte ich in
meinem Text nicht erwähnt, weil ich das nicht für das Problem hielt,
sorry (war auch schon ziemlich spät für mich).

Somit kann ich folgendes Ergenis präsentieren:
es sei
volatile int tmp, x;

Multiplikation int Variable mit int Konstante:
    tmp = x * (185);
 180:  10 91 38 01   lds  r17, 0x0138
 184:  89 eb         ldi  r24, 0xB9  ; 185
 186:  18 9f         mul  r17, r24
 188:  c0 01         movw  r24, r0
 18a:  11 24         eor  r1, r1
 18c:  9a 83         std  Y+2, r25  ; 0x02
 18e:  89 83         std  Y+1, r24  ; 0x01

Multiplikation int Variable mit float Konstante:
    tmp = x * (18.6*10);
 190:  81 2f         mov  r24, r17
 192:  99 27         eor  r25, r25
 194:  aa 27         eor  r26, r26
 196:  97 fd         sbrc  r25, 7
 198:  a0 95         com  r26
 19a:  ba 2f         mov  r27, r26
 19c:  bc 01         movw  r22, r24
 19e:  cd 01         movw  r24, r26
 1a0:  c8 d3         rcall  .+1936     ; 0x932 <__floatsisf>
 1a2:  dc 01         movw  r26, r24
 1a4:  cb 01         movw  r24, r22
 1a6:  20 e0         ldi  r18, 0x00  ; 0
 1a8:  30 e0         ldi  r19, 0x00  ; 0
 1aa:  4a e3         ldi  r20, 0x3A  ; 58
 1ac:  53 e4         ldi  r21, 0x43  ; 67
 1ae:  bc 01         movw  r22, r24
 1b0:  cd 01         movw  r24, r26
 1b2:  17 d4         rcall  .+2094     ; 0x9e2 <__mulsf3>
 1b4:  dc 01         movw  r26, r24
 1b6:  cb 01         movw  r24, r22
 1b8:  bc 01         movw  r22, r24
 1ba:  cd 01         movw  r24, r26
 1bc:  9d d3         rcall  .+1850     ; 0x8f8 <__fixsfsi>
 1be:  dc 01         movw  r26, r24
 1c0:  cb 01         movw  r24, r22
 1c2:  9a 83         std  Y+2, r25  ; 0x02
 1c4:  89 83         std  Y+1, r24  ; 0x01

Multiplikation int Variable mit float Konstante und typecast:
    tmp = x * (unsigned int)(18.7*10);
 1c6:  8b eb         ldi  r24, 0xBB  ; 187
 1c8:  18 9f         mul  r17, r24
 1ca:  c0 01         movw  r24, r0
 1cc:  11 24         eor  r1, r1
 1ce:  9a 83         std  Y+2, r25  ; 0x02
 1d0:  89 83         std  Y+1, r24  ; 0x01

Das letztere sieht doch schon viel freundlicher aus.

Vielen Dank für die Hilfe.

Gruss Bernd

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.