2012-02-12 7 views
7

De http://www.learncpp.com/cpp-tutorial/79-the-stack-and-the-heap/¿Cómo se accede a las variables locales de función desde la pila?

Aquí es la secuencia de pasos que tiene lugar cuando una función es llamada :

  1. La dirección de la instrucción más allá de la llamada a la función se inserta en la pila. Así es como la CPU recuerda a dónde ir después de que la función regrese.
  2. La sala se crea en la pila para el tipo de devolución de la función. Esto es solo un marcador de posición por ahora.
  3. La CPU salta al código de la función.
  4. La parte superior actual de la pila se mantiene en un puntero especial llamado marco de pila.
  5. Todo lo agregado a la pila después de este punto se considera "local" para la función.
  6. Todos los argumentos de funciones se colocan en la pila.
  7. Las instrucciones dentro de la función comienzan a ejecutarse.
  8. Las variables locales se insertan en la pila tal como están definidas.

No estoy seguro de cómo funciona el punto # 6. Si todos los argumentos de funciones se colocan en la pila, ¿cómo se accede?

Si, por ejemplo, hay tres argumentos a, y bc y se colocan en la pila como este de arriba

| a | 
| b | 
| c | 
| | 
... 
|___| 

Ahora lo que sucede cuando la función quiere acceder c? ¿Se salieron a y b?

+1

me parece imposible que el paso 3 pase antes de las 6: debe haber * dentro * el código de función del cuerpo sobre la evaluación de la persona que llama. ¡Disparates! – CapelliC

Respuesta

1

No, no lo son. El puntero de pila (generalmente el registro esp) apunta a a, esp+8h puntos a b, esp+16h puntos a c y así sucesivamente. No es necesario que a aparezcan.

Tenga en cuenta que esto es un detalle de implementación. No deberías preocuparte por esto. El número que he dado es puramente teórico, en algunas arquitecturas las direcciones descendentes se dan a los últimos parámetros, en otras al revés. No hay garantía de que esto suceda.

EDITAR: Me parece que esa no es una fuente de información muy confiable. Habla de pila y montón, pero estos son detalles de implementación, y es posible que ni siquiera estén allí.

No hay restricciones en el estándar para que cualquier cosa se implemente a través de una pila. Por ejemplo, tengo el siguiente código generado:

void foo(int x, int y, int z) 
{ 
01241380 push  ebp 
01241381 mov   ebp,esp 
01241383 sub   esp,0CCh 
01241389 push  ebx 
0124138A push  esi 
0124138B push  edi 
0124138C lea   edi,[ebp-0CCh] 
01241392 mov   ecx,33h 
01241397 mov   eax,0CCCCCCCCh 
0124139C rep stos dword ptr es:[edi] 
    int c = x; 
0124139E mov   eax,dword ptr [x] 
012413A1 mov   dword ptr [c],eax 
    c = y; 
012413A4 mov   eax,dword ptr [y] 
012413A7 mov   dword ptr [c],eax 
    c = z; 
012413AA mov   eax,dword ptr [z] 
012413AD mov   dword ptr [c],eax 
} 
012413B0 pop   edi 
012413B1 pop   esi 
012413B2 pop   ebx 
012413B3 mov   esp,ebp 
012413B5 pop   ebp 

Así que ya ve, no hay ninguna pila allí. El tiempo de ejecución tiene acceso directo a los elementos: dword ptr [x], etc.

+0

Pero en general, una pila se implementa de forma que no se puede acceder a un elemento de ninguna otra manera que no sea una implementación de 'top()' .. ¿Qué me falta? – Lazer

+1

@Lazer: No. Stack es una estructura de datos donde puede agregar y eliminar elementos de la parte superior de la pila en tiempo constante. Nadie dijo que no puedes acceder aleatoriamente a ellos. – ybungalobill

0

Utiliza el puntero de la pila y una dirección relativa para señalar c.

11

La pila es pila metafórica. Recuerde sigue siendo una RAM, por lo que puede acceder a cada dirección sin hacer estallar el resto, si sabe lo que está buscando.

Dado que el tamaño del de variable automática se conoce en tiempo de compilación - las marcas compilador offset para cada variable, el desplazamiento se determina a partir de donde la sección variables automáticas en la pila iniciar [o la cabeza de la pila, ambos son válidos y la específica la implementación depende de la arquitectura], y solo tiene acceso a ellos: start + offset para el desplazamiento de cada variable.

+0

En cada plataforma que puedas encontrar, es una pila metafórica. Si se tratara de una pila real que solo tuviera operaciones push y pop, la función tendría que desconectar los parámetros si los necesitara "fuera de servicio". –

+0

¿en qué memoria están almacenados los desplazamientos? –

+0

@CaisManai El desplazamiento se conoce en tiempo de compilación y no necesita almacenarse en la memoria. – amit

Cuestiones relacionadas