Question

Je prépare des documents de formation en C et je veux que mes exemples pour ajuster le modèle typique de la pile.

quelle direction une pile de C se développer sous Linux, Windows, Mac OS X (PPC et x86), Solaris, et les plus récentes unix?

Était-ce utile?

La solution

La croissance de la pile ne dépend pas habituellement sur le système d'exploitation lui-même, mais sur le processeur, il est en cours d'exécution sur. Solaris, par exemple, fonctionne sur x86 et SPARC. Mac OS X (comme vous l'avez mentionné) fonctionne sur PPC et x86. Linux fonctionne sur tout de mon grand honkin' System z au travail à petite montre-bracelet chétif .

Si la CPU fournit tout type de choix, la convention d 'appel / utilisé par le système d'exploitation indique que le choix que vous devez faire si vous voulez que votre code pour appeler le code de tout le monde.

Les processeurs et leur direction sont:

  • x86:. Bas
  • SPARC: sélectionnable. La norme ABI utilise vers le bas.
  • PPC: vers le bas, je pense
  • .
  • System z:. Dans une liste chaînée, je ne plaisante pas (mais toujours vers le bas, au moins pour zLinux)
  • ARM: sélectionnable, mais Thumb2 a encodages compact seulement pour le bas (LDMIA = augmentation d'échelon après, STMDB = décrémentation avant)
  • .
  • 6502:. Vers le bas (mais seulement 256 octets)
  • 1802a RCA. Comme vous le souhaitez, sous réserve de la mise en œuvre SCRT
  • PDP11. Bas
  • 8051:. Up

Affichage mon âge sur ces quelques derniers, le 1802 est la puce utilisée pour contrôler les premières navettes (détection si les portes étaient ouvertes, je pense, en fonction de la puissance de traitement, il avait :-) et mon deuxième ordinateur, le < a href = "http://en.wikipedia.org/wiki/Comx-35" rel = "noreferrer"> COMX-35 (suivant mon ZX80 ).

Détails PDP11 glanées , 8051 détails ici .

L'architecture SPARC utilise un modèle de registre de fenêtre glissante. Les détails visibles architecturalement également un tampon circulaire de fenêtres de registres qui sont valides et mis en cache en interne, avec des pièges quand cela plus / sousverses. Voir pour plus de détails. Comme le manuel explique SPARCv8 , SAVE et instructions RESTORE sont comme ADD instructions, plus enregistrer-fenêtre rotation. En utilisant une constante positive au lieu du négatif habituelle donnerait une pile de plus en plus vers le haut.

La technique SCRT mentionnée ci-dessus est un autre - le 1802 a utilisé une partie ou il est seize registres de 16 bits pour SCRT (appel standard et technique de retour). L'un était le compteur de programme, vous pouvez utiliser un registre comme le PC avec l'instruction SEP Rn. L'un était le pointeur de la pile et deux ont été mis toujours pointer vers l'adresse de code SCRT, un pour les appels, l'un pour le retour. Non registre a été traité d'une manière spéciale. Gardez à l'esprit ces détails sont de la mémoire, ils ne peuvent pas être tout à fait correct.

Par exemple, si R3 était le PC, R4 est l'adresse d'appel de SCRT, R5 est l'adresse de retour SCRT et R2 était la « pile » (guillemets car il est mis en œuvre dans le logiciel), SEP R4 fixerait R4 être le PC et commencer à exécuter le code d'appel SCRT.

Il serait alors magasin R3 sur la R2 « pile » (je pense que R6 a été utilisé pour le stockage temporaire), le réglage vers le haut ou vers le bas, prenez les deux octets suivants R3, les charger dans R3, puis faire courir et SEP R3 à la nouvelle adresse.

Pour revenir, il rassemblerait qui SEP R5 l'ancienne adresse de la pile R2, ajouter deux à lui (pour ignorer les octets d'adresse de l'appel), le charger dans R3 et de commencer à courir <=> précédent code.

Très difficile à envelopper votre tête autour d'abord, après tout le code stack 6502/6809 / z80 mais toujours élégant dans un bang-votre-tête contre le mur sorte de chemin. Aussi l'une des grandes caractéristiques de vente de la puce était une suite complète de 16 registres de 16 bits, en dépit du fait que vous avez perdu immédiatement 7ceux (5 pour SCRT, deux pour le DMA et les interruptions de la mémoire). Ahh, le triomphe du marketing sur la réalité: -)

System z est en fait assez similaire, en utilisant ses registres R14 et r15 pour appel / retour.

Autres conseils

C ++ (adaptable à 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);
    }
}

L'avantage de plus en plus vers le bas est dans les systèmes plus anciens de la pile était généralement en haut de la mémoire. Les programmes généralement remplis mémoire à partir du fond ainsi ce genre de gestion de la mémoire a minimisé la nécessité de mesurer et de placer le bas de la pile quelque part sensible.

Stack pousse vers le bas sur x86 (défini par l'architecture, par incréments de pop pointeur de pile, appuyez sur décréments.)

Dans MIPS il n'y a pas d'instruction push / pop. Tous les POUSSE / POPS sont faites explicitement par la charge / magasin par rapport au pointeur de pile, puis régler manuellement le pointeur $sp. Cependant, comme tous les registres (sauf $0) sont à usage général, en théorie any registre peut être un pointeur de pile et la pile peut se développer dans toutes les directions du programmeur veut. MIPS ABIs généralement la croissance vers le bas.

Dans Intel 8051 la pile grossit jusqu'à, sans doute parce que l'espace mémoire est si minuscule (128 octets dans la version originale) qu'il n'y a pas tas et vous n'avez pas besoin de mettre la pile au-dessus de sorte qu'il va être séparé de le tas croissant de bas.

Il pousse vers le bas, car la mémoire allouée au programme a les « données permanentes » code à savoir pour le programme lui-même au fond, puis le tas au milieu. Vous avez besoin d'un autre point fixe à partir de laquelle la pile de référence, de sorte que vous quitte le sommet. Cela signifie que la pile grandit vers le bas, jusqu'à ce qu'il soit éventuellement adjacent à des objets sur le tas.

Sur la plupart des systèmes, pile grossit vers le bas, et mon article https://gist.github.com/ CPQ / 8598782 explique pourquoi il pousse vers le bas. La raison en est que l'agencement optimal est de deux régions de mémoire croissante (de segment de mémoire et pile).

Juste un petit plus des autres réponses, qui, autant que je sache ne l'ai pas touché ce point:

vu se développer vers le bas de la pile prend toutes les adresses dans la pile ont un décalage positif par rapport au pointeur de pile. Il n'y a pas besoin de compensations négatives, car ils ne pointer vers l'espace de pile utilisé. Cela simplifie l'accès aux emplacements de pile lorsque le processeur prend en charge d'adressage-StackPointer relative.

De nombreux processeurs ont des instructions qui permettent d'accéder à un effet positif uniquement décalé par rapport à un certain registre. Ceux-ci incluent de nombreuses architectures modernes, ainsi que des anciens. Par exemple, le pouce de l'ARM ABI prévoit STACKPOINTER-accès relatif à un mot codé de décalage positif dans une seule instruction de 16 bits.

Si la pile a augmenté vers le haut, tous les décalages utiles par rapport à la StackPointer serait négative, ce qui est moins intuitive et moins pratique. Il est également en désaccord avec d'autres applications de registre-adressage relatif, par exemple pour accéder à des champs d'un struct.

Cette macro devrait le détecter à l'exécution sans 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;
}
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top