stack — вызовы функций во время стандартного выполнения программы на c ++

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

int func(int a)
{
int b=2;
int c,d,e,f,g;
//some code which involves a,b,c,d,e,f,g
}

int main()
{
int s=3;
func(s);
}

Теперь, что происходит, когда main начинает выполнение:
1. Он толкает в стек
2. Он вызывает func ()
3.func () помещает b, c, d, e, f, g в стек
4. Теперь, когда выполняется код, включающий a, b, c, d, e, f.g, для того, чтобы узнать значение всех локальных переменных функции func (), нужно будет вытолкнуть. Затем получается значение а. Теперь, если снова нужно использовать b.c.d.e.f.g, как будут получены их значения (потому что они уже были извлечены)?

1

Решение

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

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

6

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

Эквивалентный код для void func (int a)

    void func(int a)
{
00413880  push        ebp
00413881  mov         ebp,esp
00413883  sub         esp,108h
00413889  push        ebx
0041388A  push        esi
0041388B  push        edi
0041388C  lea         edi,[ebp-108h]
00413892  mov         ecx,42h
00413897  mov         eax,0CCCCCCCCh
0041389C  rep stos    dword ptr es:[edi]
int b=2;
0041389E  mov         dword ptr [b],2
int c,d,e,f,g;
//some code which involves a,b,c,d,e,f,g
}

Теперь давайте посмотрим эквивалентный ассемблерный код для кода ниже:

    void func(int a)
{
int b=2;
int c,d,e,f,g;
c = 10 ;
d = 15 ;
e = 20 ;
a = a + 2 ;
}

Код сборки ::

    void func(int a)
{
00413880  push        ebp
00413881  mov         ebp,esp
00413883  sub         esp,108h
00413889  push        ebx
0041388A  push        esi
0041388B  push        edi
0041388C  lea         edi,[ebp-108h]
00413892  mov         ecx,42h
00413897  mov         eax,0CCCCCCCCh
0041389C  rep stos    dword ptr es:[edi]
int b=2;
0041389E  mov         dword ptr [b],2
int c,d,e,f,g;
c = 10 ;
004138A5  mov         dword ptr [c],0Ah
d = 15 ;
004138AC  mov         dword ptr [d],0Fh
e = 20 ;
004138B3  mov         dword ptr [e],14h
a = a + 2 ;
004138BA  mov         eax,dword ptr [a]
004138BD  add         eax,2
004138C0  mov         dword ptr [a],eax
}

Таким образом, хотя они помещаются в стек (ESP или SP), но указатель на каждую из локальных переменных также сохраняется, так что к ним можно легко получить доступ при необходимости.

Мол, когда код нужно использовать переменная а, dword ptr [a] просто перемещен, чтобы зарегистрироваться EAX.

ПРИМЕЧАНИЕ. Технически не выдвигается, но настраивается для соответствия всем переменным. (Предоставлено Иоахимом Пилеборгом)

1

чтобы узнать значение всех локальных переменных функции func ()
Эта строка хотя и грамматически неоднозначна. Я предполагаю, что вы хотите сказать, что переменные всплывают при использовании функцией.

Но на самом деле локальные переменные выявляются только тогда, когда функция возвращается к вызывающей стороне.
При условии, что они автоматические.
С другой стороны, когда функция хочет получить доступ (чтение / запись) к переменной. Он использует смещение (расстояние) от базы для доступа к ним, поэтому не возникает вопроса о том, что переменные могут быть выведены во время доступа к ним для оценки.

0
По вопросам рекламы [email protected]