Параметры функции (включая, но не ограничиваясь main
) уже находятся в стеке при входе в функцию. Пространство, которое вы выделяете внутри функции, предназначено для локальных переменных. Для функций с простыми типами возврата, такими как int
, возвращаемое значение обычно будет в регистре (eax
, с типичным 32-разрядным компилятором на x86).
Если, например, main
было что-то вроде этого:
int main(int argc, char **argv) {
char a[35];
return 0;
}
... мы ожидаем, что в стеке будет выделено не менее 35 байт, когда мы введем main, чтобы освободить место для a
. Предполагая 32-битную реализацию, она обычно округляется до следующего кратного 4 (в данном случае 36) для поддержания 32-битного выравнивания стека. Мы не ожидаем увидеть пространство, выделенное для возвращаемого значения. argc
и argv
будут в стеке, но они уже будут в стеке до ввода main
, поэтому main
не нужно будет ничего делать, чтобы выделить для них место.
В случае выше, после выделения места для a
, a
обычно начинается в [esp-36]
, argv
будет в [esp-44]
и argc
будет в [esp-48]
(или эти два может быть перевернут - в зависимости от того, были ли аргументы сдвинуты слева направо или справа налево). Если вам интересно, почему я пропустил [esp-40]
, это будет обратный адрес.
Редактировать: вот схема стека при входе в функцию и после настройки фрейма стека:
![enter image description here](https://i.stack.imgur.com/fmybV.png)
Редактировать 2: Исходя из вашего обновленного вопроса, то, что у вас есть, является немного окольным, но не особенно трудным для понимания. После ввода в main
он выделяет пространство не только для переменных, локальных для main
, но и для параметров, передаваемых в функцию, которую вы вызываете из main
.
Это составляет, по крайней мере, часть выделенного дополнительного пространства (хотя не обязательно все).