2010-03-08 7 views
7

jako początkujący asm, sprawdzam generowany kod asc gcc -S, aby się uczyć.dlaczego domyślna rezerwa gcc 4.x 8 bajtów dla stosu na Linuksie podczas wywoływania metody?

dlaczego domyślna rezerwa gcc 4.x 8 bajtów dla stosu podczas wywoływania metody?

func18 to pusta funkcja bez zwrotu bez param nie zdefiniowany lokalny var. Nie mogę się domyślić, dlaczego zarezerwowano tu 8 bajtów (żadne forum/witryna nie wspomina o tym z jakiegoś powodu, ppl wygląda na pewnik) czy to jest dla% ebp po prostu push? lub zwrócić typ ?! wiele razy!

 .globl _func18 
    _func18: 
    pushl %ebp 
    movl %esp, %ebp 
    subl $8, %esp 
    .text 
+0

W rzeczywistości żadna z tych instrukcji nie ma sensu ... funkcja bez zmiennych lokalnych nie musi ustawiać wskaźnika ramki – Martin

+0

Prawdopodobnie zależy to od poziomu optymalizacji. Czy możesz dołączyć kompletny wygenerowany kod do funkcji? –

+2

Czy to miejsce dla adresu powrotu i wskaźnika ramki stosu? – jdizzle

Odpowiedz

0

Jak wspomniano wyżej o Richardzie, to wszystko z powodu optymalizacji, pokazanej poniżej. ale nadal nie mam pojęcia, dlaczego 8 bajtów zarezerwowanych jest czymś zoptymalizowanym ?!

oryginalny C

void func18() {} 
int main() {return 0;} 

kompilacji bez flagi optymalizacji określonych

.text                     
.globl _func18 
_func18: 
    pushl %ebp 
    movl %esp, %ebp 
    subl $8, %esp 
    leave 
    ret 
.globl _main 
_main:                      
    pushl %ebp 
    movl %esp, %ebp 
    subl $8, %esp 
    movl $0, %eax 
    leave 
    ret 
    .subsections_via_symbols 

-os optymalizacji flagi rezerwowy nie więcej stos

.text 
.globl _func18 
_func18: 
    pushl %ebp 
    movl %esp, %ebp 
    leave 
    ret 
.globl _main 
_main: 
    pushl %ebp 
    xorl %eax, %eax 
    movl %esp, %ebp 
    leave 
    ret 
    .subsections_via_symbols 
+2

umieścić to w pytaniu, a nie w oddzielnej odpowiedzi – moo

0

Łatwy sposób sprawdzenia: Czy pusta funkcja wywołuje inną funkcję z jednym parametrem. Jeśli parametr jest przechowywany bezpośrednio na stosie (bez pchania), to jest to, do czego służy dodatkowa przestrzeń.

+0

Próbowałem wcześniej, wydaje się nie odnosić się z nim – nikcname

8

Niektóre instrukcje wymagają wyrównania określonych typów danych do 16-bajtowej granicy (w szczególności typu danych SSE __m128). Aby spełnić to wymaganie, gcc zapewnia, że ​​stos jest początkowo wyrównany do 16 bajtów i przydziela przestrzeń stosu w wielokrotnościach 16 bajtów. Jeśli wymagany jest tylko 4-bajtowy adres zwrotny i 4-bajtowy wskaźnik ramki, potrzeba 8 dodatkowych bajtów, aby zachować wyrównanie stosu do 16-bajtowej granicy. Jeśli jednak gcc ustali, że dodatkowe wyrównanie jest niepotrzebne (tj. Fantazyjne typy danych nie są używane i nie są wywoływane żadne funkcje zewnętrzne), to może pominąć wszelkie dodatkowe instrukcje używane do wyrównania stosu. Analiza niezbędna do ustalenia tego może wymagać wykonania określonych cykli optymalizacji.

Zobacz także dokumentację gcc dla opcji -mpreferred-stack-boundary=num.

+0

thx znak, więc to wszystko na wyrównanie danych podczas optymalizacji z Sse, bardzo rozsądne, jak wyłączyć optymalizację i subl 8 dolarów % esp nie ma. gcc ref jest bardzo przydatny !!! tylko jedna rzecz, podczas gdy ja dopisuję ograniczoną do stosu-granice, zastrzeżenie tylko chg między 3 a 4, od 4 do 12, to trzyma się 8 bajtów, myślałem, że rezerwacja powinna wynosić 20 bajtów, nie? – nikcname

+0

Jeśli użyłeś -mpreferred-stack-boundary = 12, to w dowolnej funkcji, która wywołuje funkcje zewnętrzne, alokuje przestrzeń stosu w wielokrotnościach 2^12 = 4096 bajtów. Jeśli nie wywołujesz żadnych funkcji zewnętrznych, często będziesz w stanie dowiedzieć się, że utrzymywanie tego wyrównania nie jest potrzebne dla kodu, który generuje (zależy to od twojej dokładnej wersji gcc, opcji i architektury docelowej). – mark4o

+0

, więc masz na myśli w przypadku func bez wywoływania zewnętrznego func, gcc po prostu trzymać z 8 bajtów domyślnie? – nikcname

Powiązane problemy