(Je pense qu'il y a une bonne chance de cette question, soit une duplication ou une réponse d'une autre manière déjà, mais la recherche de la réponse est dure grâce à des interférences de «répartition des piles» et de termes connexes.) P>
J'ai un compilateur de jouet que je travaille pour une langue de script. Afin de pouvoir mettre en pause l'exécution d'un script alors qu'il est en cours et de retour au programme hôte, il possède sa propre pile: un bloc de mémoire simple avec une variable de "pointeur de pile" qui est incrémentée à l'aide des opérations de code C normales C Pour ce genre de chose et ainsi de suite. Pas intéressant jusqu'à présent. P>
Pour le moment, je compile à C. Mais je suis intéressé à enquêter sur la compilation du code de la machine, tout en conservant la pile secondaire et la possibilité de revenir au programme hôte aux points de contrôle prédéfinis. P>
Alors ... je pense que ce n'est pas probablement un problème d'utiliser les registres de pile conventionnels au sein de mon propre code, je suppose que ce qui arrive à registrer, il y a ma propre entreprise tant que tout est restauré quand il est fait (corriger moi si je me trompe sur ce point). mais em> ... Si je veux que le code de script appelle à un autre code de bibliothèque, est-il prudent de quitter le programme à l'aide de cette "pile virtuelle" ou est-il essentiel qu'il soit renvoyé le Pile originale à cette fin? P>
réponses comme Celui-ci a > et Celui-ci indique que La pile n'est pas un bloc de mémoire classique, mais qu'il s'appuie sur un comportement spécial spécifique à un système à faire avec des défauts de page et de National. P>
SO: P>
Ceci n'est évidemment pas réellement nécessaire, car il suffit de renvoyer les pointeurs à la vraie pile serait parfaitement réparable, ou à ce sujet ne les abuse pas en premier lieu et que je ne sais pas moins de registres, et je ne devrais probablement pas essayer faire du tout (non le moindre en raison d'être évidemment hors de ma profondeur). Mais je suis toujours curieux de toute façon. Voulez-vous savoir comment ces sortes de choses fonctionnent. P>
3 Réponses :
Toutes ces réponses sont basées sur des "architectures de processeur communes", et comme cela implique la génération de code d'assembleur, il doit être "spécifique à la cible" - si vous décidez de le faire sur le processeur x, qui a une manipulation étrange de pile ci-dessous ne vaut évidemment pas la screenurface, il est écrit sur [Substitut du papier]. Pour le X86 en général, les détentements ci-dessous, sauf indication contraire.
is it safe to move the stack pointers into some other area of memory?
Toute algorithme récursive peut être transformée (généralement assez indolère) en une itérative très similaire qui utilise une structure de pile allouée en tas ("pile" dans le sens de la structure de données).
Oui, convenu. Mais alors qu'il est relativement facile d'une perspective technique, il ajoute une couche de complexité à certains code qui a commencé réel simple. Un arbre binaire (bien équilibré) peut effectuer une recherche à travers des entrées de 1 M en 20 niveaux de récursivité - en supposant que les données stockées pour chaque niveau de récursivité ne soient pas trop grandes, c'est certainement dans les limites d'une pile équitablement assez petite.
La réponse semble bonne'n'clear, merci! En ce qui concerne la récursion, je prévoyais de faire la deuxième pile raisonnablement grande, alors n'inquiétait pas particulièrement de petites situations récursives délimitées.
Eh bien, il est évident que la récursion [ou «grande limite»] est évidemment rarement une bonne solution à tout problème. Si vos niveaux de récursivité ne sont pas «raisonnablement prévisibles et moins de quelques dizaines», la récursivité est probablement la mauvaise solution pour le problème. Et oui, faire la pile raisonnablement grosse économiser beaucoup d'autres tracas aussi.
Typiquement, sur x86, vous pouvez utiliser la pile existante sans aucun problème aussi longtemps que: p>
POP code> ou Ajouter ESP, Positive_Value Sous-ESP, négatif_value code>) au-delà de votre Le code commence par (si vous le faites, interruptions ou rappels asynchrones (signaux) ou toute autre activité à l'aide de la pile détruira son contenu) LI>
- Vous ne causez aucune exception de processeur (si vous le faites, le code de traitement des exceptions pourrait ne pas être capable de dérouler la pile au point le plus proche où l'exception peut être manipulée) li>
ul>
La même chose s'applique à l'utilisation d'un bloc de mémoire différent pour une pile temporaire et un point de pointage ESP code> à sa fin. P>
Le problème avec la manipulation des exceptions et le déroulement de la pile a à voir avec le fait que votre code C et C ++ compilé contient certaines structures de données liées à la manutention d'exception, telles que les gammes de EIP code> avec les liens vers leur Les gestionnaires respectifs des exceptions (ceci indique où le gestionnaire d'exception le plus proche est pour chaque morceau de code) et il existe également des informations relatives à l'identification de la fonction d'appel (c'est-à-dire où l'adresse de retour est sur la pile, etc.), de sorte que vous pouvez modifier des exceptions. . Si vous venez de brancher le code de la machine brute dans ce "cadre", vous n'allongerez pas correctement ces structures de données de manipulation d'exception pour la couvrir, et si les choses vont mal, elles iront probablement très tort (l'ensemble du processus peut se bloquer ou Devenez endommagé, malgré vous avoir des gestionnaires d'exception autour du code généré). P>
Alors, oui, si vous êtes prudent, vous pouvez jouer avec des piles. P>
Vous pouvez utiliser n'importe quelle région que vous aimez pour la pile du processeur (modulo les protections de mémoire). p>
essentiellement, vous chargez simplement le registre ESP ("MOV ESP, ...") avec un pointeur de la nouvelle zone, mais vous avez réussi à l'allouer. P>
Vous devez avoir assez pour votre programme em> et tout ce qu'il pourrait appeler (par exemple, une API Windows OS) et quels que soient les comportements amusants de l'OS. Vous pourrez peut-être déterminer combien d'espace votre code a besoin; Un bon compilateur peut facilement faire cela. Déterminer combien besoin de Windows est plus difficile; Vous pouvez toujours allouer «beaucoup trop», ce qui est ce que les programmes Windows ont tendance à faire. p>
Si vous décidez de gérer cet espace fermement, vous devrez probablement changer de piles pour appeler des fonctions Windows. Ça ne suffira pas; Vous serez probablement brûlé par différentes fenêtres surprises. Je décris l'un d'eux ici Windows: évitez de pousser le contexte complet X86 sur la pile . J'ai des solutions médiocres, mais pas de bonnes solutions pour cela. P>
Les réponses à ces questions seront très spécifiques à la plate-forme. S'il vous plaît mentionner quelle plate-forme vous travaillez.
Pouvez-vous être plus précis ce que vous voulez faire? Peut-être fournir un exemple de que voulez-vous dire par votre pointeur de pile virtuel et la manière dont vous avez l'intention de retourner le contrôle à un processus d'accueil?
Le pointeur de pile virtuel n'est qu'une variable C normale qui pointe quelque part dans le bloc de mémoire. "Retour au programme d'accueil" signifie littéralement des moyens simplement de revenir à partir de la fonction de script (donc si nous gênons avec des registres, cela signifierait les définir comme ils ont été trouvés avant de revenir). Essentiellement les mêmes choses que vous auriez dans un interprète; L'objet Interprète maintient son propre État de programme distinct.
Avez-vous envisagé simplement d'exécuter l'interprète (ou quoi que ce soit) dans un fil séparé? De cette façon, il va automatiquement obtenir une belle pile gérée par le système d'exploitation et évitera l'une de vos préoccupations ci-dessus!