La pila de llamadas comienza en la parte inferior o superior?

10

Una pila es algo que se acumula de abajo hacia arriba.

Por lo tanto, una pila de llamadas agrega nuevos elementos en la pila cuando se invocan funciones con elementos que se eliminan de la pila a medida que cada función termina hasta que la pila está vacía y luego termina el programa.

Si lo anterior es correcto, ¿por qué las personas se refieren al control que mueve "hacia arriba" la pila de llamadas? Seguramente el control se mueve hacia abajo en la pila de llamadas hasta que llega al fondo.

CJ7
fuente
Cuando se llama a una función, se agrega un elemento a la parte superior de la pila y el control se pasa a esa función. Por lo tanto, el control se mueve desde el elemento subyacente en la pila hasta el elemento superior, hacia arriba.
treecoder
1
@greengit: la expresión "subir la pila de llamadas" se usa con excepciones, donde el control en realidad se mueve de la manera opuesta.
Michael Borgwardt
@MichaelBorgwardt: Estás en lo correcto.
treecoder
1
@MichaelBorgwardt: He visto la expresión "errores subir la pila de llamadas". Seguramente eso es incorrecto.
CJ7

Respuestas:

8

Hay dos posibles razones para este uso:

  • En el contexto de las excepciones, el control se mueve a la función / método de llamada, y esta jerarquía de llamadas generalmente se visualiza con el método principal en la parte superior y las llamadas de método que forman una jerarquía hacia abajo, con un nivel decreciente de abstracciones. En esta jerarquía, una excepción se mueve hacia arriba.

  • La pila de programas real en una aplicación x86 normal se invierte, es decir, crece hacia abajo. Las instrucciones de código de máquina PUSH / PUSHW / PUSHD disminuyen el puntero de la pila. Otras arquitecturas pueden compartir este modelo.

Michael Borgwardt
fuente
¿No es la idea de arriba hacia abajo contraria al concepto cotidiano de que una "pila" es una pila de elementos que comienzan en la parte inferior?
CJ7
@CraigJ: también lo es el hecho de que los bits de cada byte del contenido de la pila se almacenarán físicamente en chips separados. ¿A quien le importa?
Michael Borgwardt
1

Todo depende de la definición de las palabras; ¿Qué quiere decir exactamente con las palabras "arriba" y "abajo" en este contexto, y también sobre la implementación del sistema operativo o la arquitectura de la computadora.

Recuerdo lo siguiente de hace mucho tiempo, cuando estaba programando en el Commodore 64. La memoria entre la dirección $ 0800 (2048) y $ 9FFF (40959) estaba reservada para los programas BASIC. El código de su programa BASIC se almacenó a partir de la dirección más baja ($ 0800, creciendo a partir de ahí). La pila, para almacenar variables y direcciones de retorno de subrutinas, comenzó en la parte superior ($ 9FFF) de ese rango y creció hacia direcciones más bajas. Entonces, en este contexto, era lógico ver que la pila crecía hacia abajo, y cuando regresa de una subrutina, el marco de la pila de la subrutina se descarta incrementando el puntero de la pila, de modo que podría decir que estaba "subiendo la pila" cuando regresando de una subrutina.

No sé cómo funciona en versiones modernas de, por ejemplo, procesadores Windows o Intel x86. Tal vez la pila funciona al revés, es decir, crece de direcciones más bajas a más altas. Si ese fuera el caso, entonces probablemente usarías las palabras "arriba", "abajo" y "arriba", "abajo" exactamente al revés.

Jesper
fuente
0

Para llamar a una función como foo (6, x + 1) ...

  1. Evaluar las expresiones de parámetros reales, como x + 1, en el contexto de la persona que llama.
  2. Asigne memoria para los locales de foo () empujando un "bloque local" de memoria adecuado en una "pila de llamadas" en tiempo de ejecución dedicada a este propósito. Para parámetros pero no variables locales, almacene los valores del paso (1) en la ranura apropiada en el bloque local de foo ().
  3. Almacene la dirección de ejecución actual de la persona que llama (su "dirección de retorno") y cambie la ejecución a foo ().
  4. foo () se ejecuta con su bloque local convenientemente disponible al final de la pila de llamadas.
  5. Cuando finaliza foo (), sale sacando sus locales de la pila y "regresa" a la persona que llama utilizando la dirección de retorno previamente almacenada. Ahora los locales de la persona que llama están al final de la pila y puede reanudar la ejecución.

Referencia:

http://cslibrary.stanford.edu/102/PointersAndMemory.pdf (p15)

CodeART
fuente
Tenga en cuenta que esto es muy específico de la convención de llamada. Existen convenciones de llamadas que permiten a la persona que llama limpiar, la mayoría usa al menos algunos registros, etc.
0

Si conceptualiza una pila como una cosa de abajo hacia arriba, como un cilindro con pelotas de tenis dentro de la realidad gravitacional normal, el control se mueve hacia arriba de la pila a medida que se llaman funciones. A medida que se completan las funciones, el control se mueve hacia abajo en la pila.

Si conceptualiza una pila como una cosa de arriba hacia abajo, como el mismo cilindro de pelotas de tenis pero con gravedad invertida, entonces el control se mueve hacia abajo de la pila como se llaman las funciones y hacia arriba de la pila cuando se completan las funciones.

Ambos son solo modelos en su cabeza y son esencialmente totalmente arbitrarios. Puede conceptualizarlo como una cosa de lado a lado si lo prefiere, pero podría tener problemas para comunicarse con las personas. Personalmente, creo que si A llama a B y B llama a C, C es la parte inferior de la pila (realidad gravitacional invertida) y si se produce una excepción en C, desea hacer que esa excepción "suba" a A. Creo que esta puede ser la uso del lenguaje más común porque la sensación es que C está en el fondo y A es la parte superior. La primera función es más intuitiva para mí y las funciones se vuelven más profundas en cada llamada.

Ken Falk
fuente