Сколько места выделяется путем вычитания из% esp в вызове функции?

C ++, сборка ATT

У меня есть следующий код сборки:

push %ebp
mov  %esp, %ebp
sub $0x28, %esp
(...)

Мой учебник утверждает, что вычитая 0x28 из% esp (как часть формирования стека), 12 байтов выделяется для переменных. Почему вычитание десятичного числа 40 из стека выделяет 12 байтов?

6

Решение

Это выделяет 40 байтов в стеке. Тем не менее, есть и другие применения, кроме локальных переменных, поэтому я предполагаю, что остальное используется для выравнивания и аргументов для будущего вызова функции.

Так как аргументы функции также передаются в стеке, должно быть место для любого, который эта функция хочет передать другой. Можно выделить это пространство при выполнении вызова с помощью push, но это довольно распространено, чтобы выделить место один раз в начале функции и просто использовать mov чтобы поместить данные в положение позже. Если ваша функция использует 12 байтов для локальных переменных, это оставляет до 28 для аргументов функции, которые будут использоваться позже.

Также может быть немного больше выделено для выравнивания. В дополнение к выравниванию переменных, упомянутому Джерри, многие системы ожидают, что указатель стека будет выровнен по определенному значению, поэтому его необходимо сохранить, если вы собираетесь выполнить вызов функции. В 32-битных системах это часто 8 байтов, но в этом случае также может быть 16.

5

Другие решения

Я подозреваю, что вы, возможно, неправильно прочитали свою книгу, но если нет, мне кажется, что книга по этому поводу ошибается.

Вычитание 40 из указателя стека выделяет 40 байтов. Это не может всегда быть точно правильным1, но любое отклонение от этого обычно будет довольно маленьким.


  1. Например, если вы выделите 8-байтовый объект в 32-битном коде, он может выделить некоторое дополнительное пространство (всего 12 байтов), чтобы он мог гарантировать, что 8-байтовый объект имеет 8-байтовое выравнивание. Аналогично, в 32-битном коде вы обычно можете настраивать указатель стека (по крайней мере) с 32-битными приращениями, так что функция, которая имеет один char Локальная переменная, как правило, будет по-прежнему вычитать по крайней мере 4 из указателя стека, чтобы освободить место для нее.
3