Forum: Mikrocontroller und Digitale Elektronik maßloser Speicherverbrauch bei int-Division


von F. P. (pl504)


Lesenswert?

Warum verbraucht dieses winzige AVR-Programm (z.B. atmega) mit einer 
simplen Ganzzahldivision so maßlos Programmspeicher? Es sind immerhin 
fast 5 kB.
1
int main(void) {
2
    volatile uint32_t i = 65;
3
4
    i = 3151872000 / i;
5
    while(1);
6
}

Der Wertebereich ist auf jeden Fall ausreichend. Sofern der Zähler aber 
eine Null weniger hat, normalisiert sich plötzlich der Speicherverbrauch 
halbwegs (264 B gesamt).

Ich bin sehr verwirrt. Wer kann die Sache aufklären?

von Bastler (Gast)


Lesenswert?

Erkennt GCC ein "größer 32bit int" und geht automatisch auf float über?
Eventuell das MAP-File dahingehend untersuchen.

von Helmut S. (helmuts)


Lesenswert?

Wahrscheinlich weil du mit int 3151872000 33bit benötigst.
Bis int 2147483647 reichen 32bit.

von Bastler (Gast)


Lesenswert?

Mal mit 3151872000UL probieren!

von F. P. (pl504)


Lesenswert?

Ups, hab grad den Fehler gefunden. Ich muß UL dranhängen!

danke trotzdem :)

von Mike (Gast)


Lesenswert?

Helmut S. schrieb:
> int 3151872000 33bit

Als unsigned int sind es aber nur 32bit ;-)

von m.n. (Gast)


Lesenswert?

Bei mir sind es 534 Bytes. AVR Studio 4.19.
Es findet sich eine _udivmod64 Routine sowie prologue_saves und 
epilogue_restores im Code, womit fast alle Register gerettet bzw. 
restauriert werden.

von c-hater (Gast)


Lesenswert?

F. P. schrieb:

> Der Wertebereich ist auf jeden Fall ausreichend.

Zu dumm, um aus dem Bus zu gucken...

Nein, der Wertebereich ist natürlich nicht ausreichend. Die obere Grenze 
für uint32_t ist 2^31-1, also 2.147.483.647. Jeder Klippschüler kann das 
(zumindest mit Hilfe eines Taschenrechners) ausrechnen...

3.151.872.000 ist jedenfalls deutlich größer...

von Liebhaber der Programmiersprache C (Gast)


Lesenswert?

c-hater schrieb:
> F. P. schrieb:
>
>> Der Wertebereich ist auf jeden Fall ausreichend.
>
> Zu dumm, um aus dem Bus zu gucken...
>
> Nein, der Wertebereich ist natürlich nicht ausreichend. Die obere Grenze
> für uint32_t ist 2^31-1, also 2.147.483.647. Jeder Klippschüler kann das
> (zumindest mit Hilfe eines Taschenrechners) ausrechnen...
>
> 3.151.872.000 ist jedenfalls deutlich größer...

Der Wertebereich von 32-Bit-Unsigned-Integer geht von
0 - 4.294.967.295

Scheisse, wenn man selber der Blödmann ist...

von m.n. (Gast)


Angehängte Dateien:

Lesenswert?

Ich zeige mal das Listing; da kann jeder selber sehen, was abläuft.

von Mike (Gast)


Lesenswert?

c-hater schrieb:
> Jeder Klippschüler kann das (zumindest mit Hilfe eines Taschenrechners)
> ausrechnen...

Schon doof, wenn man selbst dazu zu blöd ist und dann noch die Klappe 
aufreißt.

von Kindergärtner (Gast)


Lesenswert?

Der Cortex-M3 kanns in weniger!
1
ldr  r0, [pc, #4]
2
movs  r1, #65  ; 0x41
3
udiv  r1, r0, r1
4
.word  0xbbddc000
12 Bytes, 4-15 Takte.

von F. P. (pl504)


Lesenswert?

nächstes Mal mach ich wieder alles selbst in Assembler :P
http://elm-chan.org/docs/avrlib/div32.txt
sowas kann man sich fast einrahmen :)

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Du machst eine 64-Bit Division, denn 3151872000 ist signed in C99 und 
passt wie bereits gesagt nicht in 32 Bits.

Die Signedness hat sich von C90 nach C99 geändert, in C90 war die 
Konstamte noch unsigned.

Du kannst die Konstante als unsigned machen, z.B. 3151872000UL. Die 
passt dann in 32 Bits und es wird dann eine 32-Bit Division.

Wenn du Code sparen willst dann lass das "volatile" weg. Dann rechnet 
der Compiler das aus und es kein Division in deinem Code. Dass ist 
dann noch kürzer als von Elm Chan.

von Helmut S. (helmuts)


Lesenswert?

F. P. schrieb:
> nächstes Mal mach ich wieder alles selbst in Assembler :P
> http://elm-chan.org/docs/avrlib/div32.txt
> sowas kann man sich fast einrahmen :)

Und der Code wird auch noch 32mal ausgeführt. Das wird dauern.

von Peter D. (peda)


Lesenswert?

F. P. schrieb:
> Warum verbraucht dieses winzige AVR-Programm (z.B. atmega) mit einer
> simplen Ganzzahldivision so maßlos Programmspeicher?

Weil Du eine veraltete Lib benutzt.
Der WINAVR wird schon seit 2010 nicht mehr gepflegt, nimm was neueres.

Oder linke ne bessere 64Bit Lib hinzu:
http://www.avrfreaks.net/index.php?name=PNphpBB2&file=viewtopic&t=113673

Erst nach meinem Post fand die optimierte 64Bit-Lib auch Eingang in den 
AVR-GCC.

von F. P. (pl504)


Lesenswert?

Muß mal sehen. Ich mach nur sporadisch was mit µC; zuletzt war WinAVR 
noch aktuell. ;)

Bin momentan bei 82 % Programmspeicher, das reicht für meine Anwendung 
aus und zeitkritisch ist es auch nicht.

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Peter Dannegger schrieb:

> Weil Du eine veraltete Lib benutzt.

Nein, tut er nicht. Die im lss

Beitrag "Re: maßloser Speicherverbrauch bei int-Division"

gezeigten Routinen sind die aktuellen Routinen für 64-Bit Division.

> Der WINAVR wird schon seit 2010 nicht mehr gepflegt, nimm was neueres.

Hat er.

> Erst nach meinem Post fand die optimierte 64Bit-Lib auch Eingang in den
> AVR-GCC.

...was aber weder inhaltlich noch ursächlich mit diesem Post zu tun 
hat(te).

von Peter D. (peda)


Lesenswert?

Johann L. schrieb:
> ...was aber weder inhaltlich noch ursächlich mit diesem Post zu tun
> hat(te).

Doch, die 5kB Explosion ist genau der Effekt.

Das lss ist nicht 5kB groß und auch nicht vom TO (F. P.).

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.