Странное выделение памяти в стеке

Тема в разделе "LANGS.C", создана пользователем MYX, 27 ноя 2008.

  1. MYX

    MYX New Member

    Публикаций:
    0
    Регистрация:
    27 ноя 2008
    Сообщения:
    3
    Имеется компилятор GNU 3.4.2 из MinGW.

    Например, компилируем и дизассемблируем такую простую функцию:

    int f(int a, int b, int c)
    {
    int array[3];

    array[1] = a;
    array[2] = b;
    array[3] = c;

    return array[1];
    }

    Дизассемблированный код:

    004012B2 /$ 55 PUSH EBP
    004012B3 |. 89E5 MOV EBP,ESP
    004012B5 |. 83EC 18 SUB ESP,18
    004012B8 |. 8B45 08 MOV EAX,DWORD PTR SS:[EBP+8]
    004012BB |. 8945 EC MOV DWORD PTR SS:[EBP-14],EAX
    004012BE |. 8B45 0C MOV EAX,DWORD PTR SS:[EBP+C]
    004012C1 |. 8945 F0 MOV DWORD PTR SS:[EBP-10],EAX
    004012C4 |. 8B45 10 MOV EAX,DWORD PTR SS:[EBP+10]
    004012C7 |. 8945 F4 MOV DWORD PTR SS:[EBP-C],EAX
    004012CA |. 8B45 EC MOV EAX,DWORD PTR SS:[EBP-14]
    004012CD |. C9 LEAVE
    004012CE \. C3 RETN

    Вот теперь вопрос, а почему собственно SUB ESP,18? И почему такие смещения у элементов массива: [EBP-14], [EBP-10], [EBP-C]?

    Стек перед возвратом из функции выглядит так:

    0022FF30 77C24E42 -----------?
    0022FF34 0000A0A0 \
    0022FF38 0000B0B0 | - Элементы массива
    0022FF3C 0000C0C0 /
    0022FF40 00401390 -----------?
    0022FF44 00004000 -----------?
    0022FF48 /0022FF78 - EBP
    0022FF4C |00401316 RETURN to 4.00401316 from 4.004012B2
    0022FF50 |0000A0A0\
    0022FF54 |0000B0B0 | - параметры функции
    0022FF58 |0000C0C0 /

    Что-то я не догоняю зачем распределилась лишняя память?
     
  2. _basmp_

    _basmp_ New Member

    Публикаций:
    0
    Регистрация:
    10 июл 2005
    Сообщения:
    2.939
    MYX
    поробуйте для начала записать вашу прогу правильно. при 3х элементах в массиве они в С индексируются 0..2, те:
    уже ошибка. Кроме того укажите опции оптимизации (после переписывания).
     
  3. meduza

    meduza New Member

    Публикаций:
    0
    Регистрация:
    15 авг 2008
    Сообщения:
    212
    MYX
    выделяется место в стеке под локальные переменные, сохраняется esp в ebp и потом через ebp обращаются к локальным переменным и переданным в функцию аргументам (обращаться через esp не очень хорошая идея, т.к. в функции он может часто менятся). Если включишь оптимизацию, то компилятор может сгенерировать лучший код.
     
  4. MYX

    MYX New Member

    Публикаций:
    0
    Регистрация:
    27 ноя 2008
    Сообщения:
    3
    Нет мне прощения...

    0022FF30 0000A0A0
    0022FF34 0000B0B0
    0022FF38 0000C0C0
    0022FF3C 00401466 ----------?
    0022FF40 00401380 ----------?
    0022FF44 00004000 ----------?
    0022FF48 /0022FF78 - EBP
    0022FF4C |0040130E RETURN to 4.0040130E from 4.004012AA
    0022FF50 |0000A0A0
    0022FF54 |0000B0B0
    0022FF58 |0000C0C0

    Оптимизация повлияла только на сам код, но не на распределение памяти в стеке. Также осталось SUB ESP,18.
     
  5. meduza

    meduza New Member

    Публикаций:
    0
    Регистрация:
    15 авг 2008
    Сообщения:
    212
    MYX
    конечно, а где по твоему функция будет хранить локальные переменные?
     
  6. _basmp_

    _basmp_ New Member

    Публикаций:
    0
    Регистрация:
    10 июл 2005
    Сообщения:
    2.939
    не исключено, что пустые локалки - алиасы на случай записи во входные параметры как в переменные, ведь они у вас не консты. Сделайте эксперимент - добавьте еще параметров, запишите в какойнить из них.
    еще очень возможен вариант, что это выравнивание блока локалок на 16. Попробуйте отключить выравнивание. не помню точно как в гну вызывается.. ключевое слово align
     
  7. MYX

    MYX New Member

    Публикаций:
    0
    Регистрация:
    27 ноя 2008
    Сообщения:
    3
    _basmp_, спасибо! Это и на самом деле оказалось выравнивание. Я это подозревал, но не мог найти соответствующих опций компилятора. Опция называется -preferred-stack-boundary=X.

    Удалось добиться такого:

    0022FF40 0000A0A0 -> array[0]
    0022FF44 0000B0B0 -> array[1]
    0022FF48 0000C0C0 -> array[2]
    0022FF4C 00004000 --- для выравнивания
    0022FF50 /0022FF78 --- сохраненный EBP
    0022FF54 |00401324 RETURN to a.00401324 from a.004012AA