Pregunta

Estoy preparando algunos de los materiales de capacitación en C y quiero que mis ejemplos a la típica pila de modelo.

¿Qué dirección C pila de crecer en Linux, Windows, Mac OSX (PPC y x86), Solaris, y el más reciente de los sistemas Unix?

¿Fue útil?

Solución

De crecimiento de la pila, por lo general no dependen del sistema operativo en sí, sino en el procesador está funcionando.Solaris, por ejemplo, se ejecuta en x86 y SPARC.Mac OSX (como se mencionó) se ejecuta en PPC y x86.Linux se ejecuta en todo, desde mi gran honkin' System z en el trabajo a un poco insignificantes reloj de pulsera.

Si la CPU proporciona cualquier tipo de elección, el ABI / la convención de llamada utilizada por el sistema operativo especifica cuál de las opciones que usted necesita hacer si usted quiere que su código para llamar a todos los demás del código.

Los procesadores y su dirección son:

  • x86:abajo.
  • SPARC:seleccionable.El estándar ABI utiliza abajo.
  • PPC:abajo, creo.
  • El sistema z:en una lista enlazada, no es broma (pero aún así, al menos de zLinux).
  • BRAZO:seleccionable, pero Thumb2 ha compacto codificaciones sólo por abajo (LDMIA = incremento después, STMDB = decremento antes).
  • 6502:abajo (pero sólo 256 bytes).
  • RCA 1802A:cualquier manera que usted desea, sujeto a SCRT aplicación.
  • PDP11:abajo.
  • 8051:hasta.

Mostrando mi edad en los últimos, el de 1802 fue el chip usado para el control de las primeras lanzaderas (detección de si las puertas estaban abiertas, sospecho, basado en la potencia de procesamiento que tenía :-) y mi segundo equipo, el COMX-35 (después de mi ZX80).

PDP11 detalles obtenida de aquí, 8051 detalles de aquí.

La arquitectura SPARC utiliza una ventana corredera de registro de modelo.La arquitectura visible detalles también incluyen un buffer circular de registro de windows que son válidos y almacenada internamente, con trampas cuando que sobre/underflows.Ver aquí para obtener más detalles.Como el SPARCv8 manual se explica, GUARDAR y RESTAURAR las instrucciones son como AGREGAR instrucciones además de registrarse en la ventana de la rotación.El uso de una constante positiva en lugar de la habitual negativa daría un alza creciente de la pila.

La mencionada SCRT técnica es otra - la de 1802 utilizar algunos o dieciséis (16-bits de los registros para SCRT (estándar llamada y volver a la técnica).Uno de ellos fue el contador de programa, se puede usar cualquier registro, como el PC con el SEP Rn de la instrucción.Uno fue el puntero de la pila y los dos se establece siempre a punto para el SCRT código de dirección, uno para llamar, uno para el regreso. No registro fue tratado de una manera especial.Tenga en cuenta estos detalles son de memoria, puede que no sean totalmente correctos.

Por ejemplo, si R3 fue el PC, R4 fue el SCRT llamada dirección, R5 fue el SCRT dirección de retorno y R2 fue la "pila" (entre comillas como se implementa en software), SEP R4 establecer R4 a la PC y empezar a correr el SCRT código de llamada.

Entonces la tienda de R3 en R2 "pila" (creo R6 se utiliza para el almacenamiento temporal), el ajuste hacia arriba o hacia abajo, coge los dos bytes siguientes R3, cargarlos en R3, a continuación, hacer SEP R3 y se ejecuta en la nueva dirección.

Para volver, lo haría SEP R5 que se tire de la vieja dirección de la R2 de la pila, añadirle dos (saltar los bytes de dirección de la llamada), cargar en R3 y SEP R3 para empezar a ejecutar el código anterior.

Muy duro para envolver su cabeza alrededor de la inicialmente después de que todos los 6502/6809/z80 basado en pila de código, pero todavía elegante en un bang-su-cabeza contra la pared una especie de camino.También una de las grandes características de venta de la ficha era una completa suite de 16 de 16 bits de los registros, a pesar del hecho de que inmediatamente perdido 7 de los (5 para SCRT, dos para el DMA y las interrupciones de la memoria).Ahh, el triunfo de la comercialización sobre la realidad :-)

El sistema z realidad es bastante similar, utilizando su R14 y R15 registros de llamada/retorno.

Otros consejos

En C ++ (adaptable a C) stack.cc :

static int
find_stack_direction ()
{
    static char *addr = 0;
    auto char dummy;
    if (addr == 0)
    {
        addr = &dummy;
        return find_stack_direction ();
    }
    else
    {
        return ((&dummy > addr) ? 1 : -1);
    }
}

La ventaja de crecer hacia abajo es en los sistemas más antiguos de la pila era típicamente en la parte superior de la memoria. Programas normalmente llenos de memoria a partir de la parte inferior por lo que este tipo de gestión de memoria reducen al mínimo la necesidad de medir y coloque la parte inferior de la pila alguna parte sensible.

pila crece hacia abajo en x86 (definida por la arquitectura, incrementos pop puntero de pila, decrementos empujar.)

En MIPS no hay push / pop instrucción. Todos los empujones / POPS se hacen explícitamente por carga / almacenamiento con respecto al puntero de pila y luego ajustar manualmente el $sp puntero. Sin embargo, como todos los registros (excepto $0) son de uso general, en teoría cualquier registro puede ser un puntero de pila, y la pila puede crecer en cualquier dirección que el programador quiere. MIPS ABIs normalmente crecen hacia abajo.

En 8051 Intel la pila crece, probablemente debido a que el espacio de memoria es tan pequeña (128 bytes en la versión original) que no hay montón y que no es necesario poner la pila en la parte superior por lo que va a ser separado de el montón creciente desde la parte inferior.

Crece hacia abajo debido a que la memoria asignada al programa tiene los "datos permanentes" código es decir, para el programa en sí en la parte inferior, a continuación, el montón en el medio. Es necesario otro punto fijo desde el cual hacer referencia a la pila, por lo que sale de la parte superior. Esto significa que la pila crece hacia abajo, hasta que es potencialmente adyacente a los objetos en el montón.

En la mayoría de los sistemas, la pila crece hacia abajo, y mi artículo en https://gist.github.com/ CPQ / 8598782 explica por qué crece hacia abajo. La razón es que es la disposición óptima de dos regiones de cultivo de memoria (heap y la pila).

Sólo una pequeña adición a las otras respuestas, que por lo que yo puedo ver, no he tocado este punto:

Tener la pila crece hacia abajo hace que todas las direcciones dentro de la pila tienen un desplazamiento positivo en relación con el puntero de pila. No hay necesidad de desplazamientos negativos, ya que sólo apuntar al espacio de pila sin usar. Esto simplifica el acceso a ubicaciones de pila cuando el procesador soporta StackPointer-direccionamiento relativo.

Muchos procesadores tienen instrucciones que permiten accesos con un solo desplazamiento positivo en relación con algún registro. Entre ellos se incluyen muchas arquitecturas modernas, así como algunos de los antiguos. Por ejemplo, el ARM pulgar ABI proporciona para los accesos StackPointer-relativa con un desplazamiento positivo codificada dentro de una sola palabra de instrucción de 16 bits.

Si la pila creció hacia arriba, todos los desplazamientos útiles relativos a la StackPointer sería negativo, que es menos intuitivo y menos conveniente. También está en contradicción con otras aplicaciones de registro-direccionamiento relativo, por ejemplo para acceder a los campos de una estructura.

Esta macro debe detectar en tiempo de ejecución sin UB:

#define stk_grows_up_eh() stk_grows_up__(&(char){0})
_Bool stk_grows_up__(char *ParentsLocal);

__attribute((__noinline__))
_Bool stk_grows_up__(char *ParentsLocal) { 
    return (uintptr_t)ParentsLocal < (uintptr_t)&ParentsLocal;
}
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top