2012-03-05 2 views
3

Рассмотрим эту простую программу Cx86 Сборка Stack Бронирование

#include <stdio.h> 

int func() 
{ 
    printf("Hello World\n"); 
    return 0; 
} 

int main() 
{ 
    printf("Hello World\n"); 
    return 0; 
} 

Это соответствующий 32-разрядную сборку составленный НКУ

.file "a.c" 
     .section  .rodata 
    .LC0: 
     .string "Hello World" 
     .text 
    .globl func 
     .type func, @function 
    func: 
     pushl %ebp 
     movl %esp, %ebp 
     subl $24, %esp 
     movl $.LC0, (%esp) 
     call puts 
     movl $0, %eax 
     leave 
     ret 
     .size func, .-func 
    .globl main 
     .type main, @function 
    main: 
      pushl %ebp 
      movl %esp, %ebp 
      andl $-16, %esp 
      subl $16, %esp 
      movl $.LC0, (%esp) 
      call puts 
      movl $0, %eax 
      leave 
      ret 
      .size main, .-main 
      .ident "GCC: (Ubuntu 4.4.3-4ubuntu5) 4.4.3" 
      .section  .note.GNU-stack,"",@progbits 

Почему НКУ резерв 24 байт для строки «Hello World» в функции 'func()', но только 16 байтов в основной функции для одной и той же строки?

+0

Это не имеет ничего общего со строкой, она никогда не загружается в стек. $ 16 в прологе основной функции заключается в том, чтобы выровнять указатель стека. Обратите внимание на команду andl. –

+0

Ханс, вы говорите о инструкции andl в основном. Его команда andl, которая выравнивает указатель стека к границе страницы. Я спрашиваю о subl $ 16, (% esp) в основной функции & subl $ 24, (% esp) в func – user1249669

ответ

0

Компилятор пытается выделить 16B для обеих функций (сомнительно, сколько ему нужно).

В «main» он просто выделяет 16B и вызывает puts. Обратите внимание, что перед вызовом стек выравнивается до 0 mod 16, потому что это требуется в ABI (т. Е. Ваш стек всегда должен быть 0 mod 16 до вызова).

В func стек входит в 12 mod 16, выровненный (из-за обратного адреса). Затем мы подталкиваем ebp, делая его 8 mod 16. Теперь мы хотим выделить 16B в стеке (аналогично основному), но мы также хотим, чтобы стек был 0 mod 16 байт, выровненный до вызова, поэтому нам нужно для вычитания 8 + 16 байтов, что равно 24.

Смежные вопросы