2013-07-02 11 views
5

Mam kompilacji następującą prostą funkcję pokazową:Dlaczego GCC generuje instrukcje dotyczące przechowywania stosów, gdy nie są one potrzebne?

int add(int a, int b) { 
    return a + b; 
} 

Oczywiście funkcja ta będzie inlined, ale załóżmy, że to dynamicznie połączone lub nie inlined z jakiegoś innego powodu. Z wyłączony optymalizacji kompilator produkuje oczekiwany kod:

00000000 <add>: 
    0: 55      push ebp 
    1: 89 e5     mov ebp,esp 
    3: 8b 45 0c    mov eax,DWORD PTR [ebp+0xc] 
    6: 03 45 08    add eax,DWORD PTR [ebp+0x8] 
    9: 5d      pop ebp 
    a: c3      ret 

Ponieważ istnieje żadna funkcja zwraca wewnątrz tej funkcji, instrukcja 0, 1 i 9 pozornie nie mają celu. Ponieważ optymalizacja jest wyłączona, jest to dopuszczalne.

Jednak podczas kompilacji przy optymalizacji pod kątem rozmiaru z -Os -s tworzony jest dokładnie ten sam kod. Wydaje się raczej nieekonomiczne zwiększenie rozmiaru funkcji o 66% dzięki tym opcjom.

Dlaczego kod nie jest zoptymalizowany pod kątem poniższych?

00000000 <add>: 
    0: 8b 45 0c    mov eax,DWORD PTR [esp+0x8] 
    3: 03 45 08    add eax,DWORD PTR [esp+0x4] 
    6: c3      ret 

Czy kompilator po prostu nie warto rozważyć tę optymalizację, czy jest to związane z innymi szczegółami, jak wyrównanie funkcji?

+0

Istnieje również możliwość, że jest to środek bezpieczeństwa przeciwko pewnym atakom szturmowym stosu. –

+0

@MarcB Myślisz o "kanarkach stosowych", które wyglądają inaczej. Wskaźniki ramek niestety nie pomagają w walce na stosie. – zwol

Odpowiedz

15

Wykonuje się to, aby zachować zdolność debuggera do przejrzenia kodu.

Jeśli naprawdę chcesz wyłączyć to spróbuj .

kompilacji Powyższy kod korzystając -Os -fomit-frame-pointer -S -masm=intel dało to:

.file "frame.c" 
    .intel_syntax noprefix 
    .text 
    .globl _add 
    .def _add; .scl 2; .type 32; .endef 
_add: 
    mov eax, DWORD PTR [esp+8] 
    add eax, DWORD PTR [esp+4] 
    ret 
    .ident "GCC: (rev0, Built by MinGW-builds project) 4.8.0" 
+1

+1 dla '-fomit-frame-poionter'. Robi dokładnie to, co chce OP. –

+0

N.B. '-fomit-frame-pointer' jest domyślnie włączone dla x86-64, chociaż możliwe, że nie dla win64. – zwol

0

Wartość EBP nie wiadomo, kiedy funkcja wejdzie. Kod mógł używać mov eax,dword ptr [esp+8] i nie zawracać sobie głowy rejestrem BP, ale wiele narzędzi do debugowania zakłada, że ​​każda lokalna zmienna ma ustalone przesunięcie względem pewnego rejestru. Nawet gdyby kompilator mógł śledzić rzeczy, które zostały przesunięte na stos i odpowiednio dostosować przesunięcia indeksowania, debuggery prawdopodobnie nie byłyby w stanie tego zrobić.

Powiązane problemy