stack - memoria - modos de direccionamiento arquitectura de computadoras
¿Por qué la dirección de pila crece hacia la disminución de las direcciones de memoria? (2)
Leí en los libros de texto que la pila crece al disminuir la dirección de la memoria; es decir, desde una dirección más alta a una dirección más baja. Puede ser una mala pregunta, pero no entendí bien el concepto. ¿Puedes explicar?
Hoy en día es en gran parte porque se ha hecho así durante mucho tiempo y muchos programas asumen que se hace de esa manera, y no hay una razón real para cambiarlo.
Cuando los dinosaurios deambulaban por la Tierra y las computadoras tenían 8kB de memoria, si tenías suerte, era una importante optimización del espacio. Pone la parte inferior de la pila en la parte superior de la memoria, creciendo, y pone el programa y sus datos en la parte inferior, con el área de malloc
creciendo. De esta forma, el único límite en el tamaño de la pila era el tamaño del programa + montón, y viceversa. Si la pila en su lugar comenzó en 4kB (por ejemplo) y creció, el montón nunca podría llegar a ser más grande que 4kB (menos el tamaño del programa) incluso si el programa solo necesitaba unos cientos de bytes de stack.
Primero, depende de la plataforma. En algunas arquitecturas, la pila se asigna desde la parte inferior del espacio de direcciones y crece hacia arriba.
Suponiendo que una arquitectura como x86 crezca hacia abajo desde la parte superior del espacio de direcciones, la idea es bastante simple:
=============== Highest Address (e.g. 0xFFFF)
| |
| STACK |
| |
|-------------| <- Stack Pointer (e.g. 0xEEEE)
| |
. ... .
| |
|-------------| <- Heap Pointer (e.g. 0x2222)
| |
| HEAP |
| |
=============== Lowest Address (e.g. 0x0000)
Para aumentar la pila, disminuirás el puntero de la pila:
=============== Highest Address (e.g. 0xFFFF)
| |
| STACK |
| |
|.............| <- Old Stack Pointer (e.g. 0xEEEE)
| |
| Newly |
| allocated |
|-------------| <- New Stack Pointer (e.g. 0xAAAA)
. ... .
| |
|-------------| <- Heap Pointer (e.g. 0x2222)
| |
| HEAP |
| |
=============== Lowest Address (e.g. 0x0000)
Como puede ver, para aumentar la pila, hemos reducido el puntero de la pila de 0xEEEE a 0xAAAA, mientras que para aumentar el montón, debe aumentar el puntero del montón.
Obviamente, esto es una simplificación del diseño de la memoria. El ejecutable real, la sección de datos, ... también se carga en la memoria. Además, los hilos tienen su propio espacio de pila.
Usted puede preguntar, ¿por qué la pila crecerá hacia abajo? Bueno, como dije antes, algunas arquitecturas hacen lo contrario, haciendo que el montón crezca hacia abajo y la pila crezca hacia arriba. Tiene sentido colocar la pila y el montón en lados opuestos, ya que evita la superposición y permite que ambas áreas crezcan libremente siempre que haya suficiente espacio de direcciones disponible.
Otra pregunta válida podría ser: ¿No se supone que el programa disminuirá / aumentará el puntero de la pila en sí? ¿Cómo puede una arquitectura imponer una sobre la otra al programador? ¿Por qué no es tan dependiente del programa ya que depende de la arquitectura? Si bien puedes luchar mucho contra la arquitectura y de alguna manera escapar de tu pila en la dirección opuesta, algunas instrucciones, especialmente las call
y ret
que modifican el puntero de la pila, van a tomar otra dirección, haciendo un desastre.