AVR-GCC: PUSH-/Pop-Orgie verhinern

Gast #5269919
Lesenswert?

In der main() sichert der AVR-GCC (ATTiny13-Quelltext) einen Haufen 
Register (s. u.)und restauriert sie am Ende wieder.

Wie kann man das verhindern?
1
int main(void)
2
{
3
 124:  2f 92         push  r2
4
 126:  3f 92         push  r3
5
 128:  4f 92         push  r4
6
 12a:  5f 92         push  r5
7
 12c:  6f 92         push  r6
8
 12e:  7f 92         push  r7
9
 130:  8f 92         push  r8
10
 132:  9f 92         push  r9
11
 134:  af 92         push  r10
12
 136:  bf 92         push  r11
13
 138:  cf 92         push  r12
14
 13a:  df 92         push  r13
15
 13c:  ef 92         push  r14
16
 13e:  ff 92         push  r15
17
 140:  0f 93         push  r16
18
 142:  1f 93         push  r17
19
 144:  cf 93         push  r28
20
 146:  df 93         push  r29
21

22
...
23

24
 2d4:  df 91         pop  r29
25
 2d6:  cf 91         pop  r28
26
 2d8:  1f 91         pop  r17
27
 2da:  0f 91         pop  r16
28
 2dc:  ff 90         pop  r15
29
 2de:  ef 90         pop  r14
30
 2e0:  df 90         pop  r13
31
 2e2:  cf 90         pop  r12
32
 2e4:  bf 90         pop  r11
33
 2e6:  af 90         pop  r10
34
 2e8:  9f 90         pop  r9
35
 2ea:  8f 90         pop  r8
36
 2ec:  7f 90         pop  r7
37
 2ee:  6f 90         pop  r6
38
 2f0:  5f 90         pop  r5
39
 2f2:  4f 90         pop  r4
40
 2f4:  3f 90         pop  r3
41
 2f6:  2f 90         pop  r2
42
 2f8:  08 95         ret
Gast #5269959
Lesenswert?

Stefan E. schrieb:
> Karl schrieb:
>> Das war einfach:
>
> Aber falsch. Das "naked" eliminiert auch Sachen, auf die du nicht
> verzichten möchtest, wie z.B. einen Stack-Frame bei lokalen Daten. Nimm
> lieber OS_main:
>
>
1
__attribute__ ((OS_main)) int main(void)

Der Code wird dadurch 6 Bytes länger.

Beide Attribute funktionieren mit meinem Programm.

Was hat es mit dem Stack-Frame auf sich?

Wo kann man näheres nachlesen?
Persönliche Seite #5270419
Lesenswert?

Kevin schrieb:
> Welche avr-gcc-Version setzt du denn ein?? Das sollte schon lange kein
> Thema mehr sein.

avr-gcc übersetzt main als Funktion mit normalem ABI, also so, dass sie 
returnt bzw. returnen kann.  Um dieses verhalten zu ändern braucht man 
dann Function Attribute wie OS_main.

Beispielsweise sichert avr-gcc-8 -Os für
1
long long vv;
2

3
int main()
4
{
5
    return vv + (vv >> 60);
6
}
Y und R8...R16 und legt brav einen Frame an.  Mit OS_main wird immer 
noch ein Frame angelegt aber keine Regs gesichert.

..und mit "naked" erhält man ein nicht-funktionierendes Programm.
#5270424
Lesenswert?

Karl schrieb:
> Stefan E. schrieb:
>> Karl schrieb:
>>> Das war einfach:
>>
>> Aber falsch. Das "naked" eliminiert auch Sachen, auf die du nicht
>> verzichten möchtest, wie z.B. einen Stack-Frame bei lokalen Daten. Nimm
>> lieber OS_main:
>>
>>
1
__attribute__ ((OS_main)) int main(void)
>
> Der Code wird dadurch 6 Bytes länger.
>

Geht es darum, mit den knappen FLASH auszukommen?
Mit
-mcall-prologues
erzeugt der avr-gcc Aufrufe zur nur noch einer zentralen Push/Pop-Orgie, 
was wenn mehrere Funktionen mit kräftigem Registerbedarf existieren, 
deutlich FLASH einspart. Der dabei genutzte Code wird je nachdem wie 
viele Register gesichert werden müssen mit unterschiedlichen 
Einsprungadressen aufgerufen und sichert/restored jeweils nur die 
gewünschten Register.
Diese Option hat schon mal einem Nachbauer des Transistortesters 
geholfen von seiner 110% FLASH-Belegung weg zu kommen.
#5270735
Lesenswert?

@Karl (Gast)

>Was genau bewirkt der fehlende Stack-Frame bei _attribute_
>((naked))?

Daß rein gar nichts an Speicherplatz für lokale Varialen in main() 
angelegt wird, sprich, man kann keine lokalen Variabeln in main() 
nutzen. Das ist aber unbedeutend, denn die kann man einfach global 
machen.
#5270784
Lesenswert?

Kevin schrieb:
> Welche avr-gcc-Version setzt du denn ein?? Das sollte schon lange
> kein
> Thema mehr sein.

Wann war das denn überhaupt mal ein Thema?

Üblicherweise macht das weder der steinzeitliche avr-gcc aus WinAVR, 
noch irgend eine aktuelle Version, auch nicht ohne jede Optimierung. 
Zumindest nicht die Versionen, die mir unter Windows bisher begegnet 
sind. Und ich schaue mir sehr regelmäßig die generierten 
Assemblerlistings an.

Oliver
#5270975
Lesenswert?

Oliver S. schrieb:
> Zumindest nicht die Versionen, die mir unter Windows bisher begegnet
> sind. Und ich schaue mir sehr regelmäßig die generierten
> Assemblerlistings an.

Dann ist deine main() einfach nur nicht "kompliziert" genug. Natürlich 
werden diese Register nur gesichert, wenn sie in der Funktion auch 
benutzt werden. Und auf die call-saved Register greift der Compiler erst 
zurück, wenn ihm die call-clobbered ausgehen.
Persönliche Seite #5271032
Lesenswert?

Stefan E. schrieb:
> Oliver S. schrieb:
>> Zumindest nicht die Versionen, die mir unter Windows bisher begegnet
>> sind. Und ich schaue mir sehr regelmäßig die generierten
>> Assemblerlistings an.
>
> Dann ist deine main() einfach nur nicht "kompliziert" genug. Natürlich
> werden diese Register nur gesichert, wenn sie in der Funktion auch
> benutzt werden.

Genau.  Und der komplizierte Code sieht im Original so aus:


Karl schrieb:
>
> ...
>

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren