10
votes

Écrire un assembleur Z80 - Lexing ASM et construire un arbre d'analyse à l'aide de la composition?

Je suis très nouveau au concept d'écriture d'un assembleur et même après avoir lu beaucoup de matériel, j'ai toujours des difficultés qui m'empressent de la tête autour de quelques concepts.

  1. Quel est le processus pour briser réellement un fichier source en jetons? Je crois que ce processus s'appelle Lexing, et j'ai cherché haut et bas pour obtenir des exemples de code réels qui ont du sens, mais je ne trouve pas une chose si simple des exemples de code très bienvenus;) p> li>

  2. Lors de l'analyse, les informations doivent-elles jamais être transmises à l'arbre? La raison pour laquelle je demande est la suivante, prenez: p>

    LD BC, NN P> LI> ol>

    Il doit être transformé en l'arballe d'analyse suivant une fois TOKENISÉ (???) P>

    11 n n
    


0 commentaires

3 Réponses :


7
votes

Il n'est pas nécessaire de construire un arbre d'analyse. Les codes OP Z80 sont très simples. Ils se composent du code OP et de 0, 1 ou 2 opérandes, séparés par des virgules. Vous avez juste besoin de diviser l'opcode dans les composants (maximum de 3) avec un analyseur très simple - aucun arbre n'est nécessaire.


6 commentaires

Qu'en est-il des adresses de mémoire relatives> une sorte d'arbre symbolique est sûrement nécessaire pour cela? peut-être même une table


Le questionneur demandait à l'analyse des codes OP. Vous avez certainement besoin d'une table de symboles pour vous aider à créer la sortie du code de la machine réelle de l'assembleur, mais c'est un problème complètement différent.


@Darknight: Ne serait toujours pas un point valide pour créer un arbre d'analyse. Par exemple, d'autres occurrences pourraient jouer une partie, telles que voici quelques chaînes de code ASM qui ont des variations de la syntaxe: étiquettes, commentaires, supports, variables globales, .dd .dw .dw .dw ne deviendraient pas plus simplifiés si un L'arbre d'analyse a été utilisé? @Neil: Pourriez-vous élaborer? Cordialement, GP


@Gary, vous pourriez le faire si vous voulez compliquer votre vie. J'ai écrit quelques assembleurs (bien que non un pour le Z80) et ils sont normalement facilement implémentés via un schéma de jeton simple (comme je l'ai suggéré dans ma réponse) et un évaluateur d'expression pour évaluer l'adresse et les autres expressions. L'expression Evlauator peut utiliser un arbre (bien qu'une pile basée elle suffit dans mon expérience), mais il n'est pas nécessaire de rendre l'arborescence d'analyse votre structure de données de base.


@Neil merci pour vos commentaires ... Vous n'avez pas d'exemple de code, n'est-ce pas? Clarifiera probablement beaucoup! :)


@Gary Désolé, le dernier assembleur que j'ai écrit était dans REXX sur le système d'exploitation principal VM / CMS de IBM. Même si j'avais le code, je ne pense pas que cela vous sera utile.



10
votes

Eh bien, la structure de l'arbre que vous voulez vraiment une instruction qui agit sur un registre et une mémoire mode d'adressage involing un déplacement de décalage et un registre d'index ressemblerait à ceci:

    INSTRUCTION-----+
    |      |        |
  OPCODE  REG     OPERAND
                  |     |
                OFFSET  INDEXREG


12 commentaires

Cela était destiné à être illustratif des arbres qu'il a besoin de construire plutôt que de correspondre à une instruction Z80 spécifique. J'ai codé beaucoup d'assembleur Z80 dans les années 1980; Je peux en savoir plus sur cela que vous ne le pensez.


Puis démontrez vos connaissances. Avez-vous écrit un assembleur Z80? Je ne l'ai pas fait, mais j'ai écrit des assembleurs 8080 et 6809, et vos conseils me semblent avoir mal à mort.


Votre expérience est probablement différente du mien. J'ai codé des assembleurs pour le Collins 8311 (CIRCA 1968), une machines de 12 et 16 bits qui ne l'ont pas réalisée dans le commerce afin que vous n'en avez pas entendu parler d'eux, des assembleurs de microcode et de l'assembleur 6809 que vous avez vu dans l'autre message. J'ai également construit une variété de fins avant compilateur (consultez mon site Web bio et mon site Web). Mes premiers assembleurs ont été construits par ad hoc et travaillaient. Des trucs depuis les années 80, j'ai construit à l'aide de lexers et d'analyseurs car il est beaucoup plus facile de préciser, de maintenir, de prolonger, de le nommer.


Mon expérience peut être qualitativement différente de la vôtre le long d'un autre axe. J'ai toujours voulu des outils pour m'aider à spécifier / analyser / manipuler des langues. J'ai passé les 25 dernières années à comprendre comment aller bien au-delà de Lex et du YACC, et maintenant des outils qui me permettent (et d'autres personnes les souhaitent). Je les utilise quotidiennement et ils sont efficaces. Sans expérimenter de tels outils, vous pourriez ne pas être convaincu. Ok, laissez beaucoup de fleurs fleurir.


Hmm. Je suis totalement en faveur des outils, mais certains outils sont assez merdiques. En plus de Bjarne Stroustrup, je suis un grand fan de descente récursive lorsqu'il s'agit d'analyser, par opposition à des outils entraînés comme YACC / Bison. Et quand il s'agit de parcourir l'assembleur Mnemonics, je suis un fan encore plus grand d'analyse ad hoc. Les assembleurs mnémoniques ne sont vraiment pas si réguliers. Mais vous savez évidemment de quoi vous parlez, alors j'ai supprimé le commentaire initial (qui était un peu grossier) et supprimé le bowvote.


Quand une descente récursive fonctionne, cela fonctionne bien. Mais cela ne fonctionne bien que sur les grammaires de taille modeste qui ne changent pas rapidement (lorsque vous construisez des DSL, la grammaire change rapidement) et qui ne nécessite aucun lookahead ni aucune information de type pour résoudre l'analyse (votre bien-aimé C ++ a un mauvais Problème de lookahead ici). Lorsque vous n'êtes pas dans cette fenêtre, des moteurs à analyses plus puissants (lisez «LIRE« Contexte gratuit ») sont meilleurs et des spécifications explicites de la grammaire complète facilitent la révise et la maintenance. Et une fois que vous avez de telles machines, il est également facile de tuer des moucherons, et vous devriez.


Eh bien, les problèmes de grammaire C ++ sont bien sûr une difficulté pour les analyseurs de descente récursive et à la table. Mais Stroustrup est enregistré (le livre de D & E, le chapitre 2), comme indiquant qu'il aurait dû utiliser un analyseur de descente récursif plutôt que sur une YACC basé sur une tâche pour mettre en œuvre CFRT (le premier compilateur C ++), qui s'est retrouvé avec le code piloté de table et RD. . Et était horrible - je parle comme un utilisateur.


DMS a un analyseur complet C ++ (gère même les dialectes GNU et MS) et utilise un schéma piloté de table (appelé GLR, une généralisation de LR) basée sur exactement le même style de grammaire que vous le voyez dans la question connexe à celle-ci. Cet analyseur C ++ a été utilisé pour effectuer des transformations automatisées massives sur de grands systèmes logiciels intégrés. L'analyseur est aussi beau que le manuel de référence C ++ lui permettra d'être suivant: -} Je parle comme un constructeur avant.


Voir cette réponse à propos de l'analyse C ++ avec de bons outils: Stackoverflow.com/questions/243383/...


Bonjour Ira, je connais votre travail et c'est extrêmement impressionnant. Sans aucune hésitation, je vous considérerais une autorité sur la question. Je suis quelque peu confus par votre réponse ici, j'ai écrit quelques petits assembleurs (pas Z80 Mind You) et je ne sais pas pourquoi vous suggéreriez d'utiliser une structure d'arborescence dans l'analyse d'une grammaire régulière comme un assembleur. Ce que vous avez démontré ci-dessus semble mieux représenté par une série de structures spécifiques imbriquées plutôt qu'à un arbre.


Les structures imbriquées et les arbres sont simplement des représentations isomorphes. Donc, sa prise de choix. La bonne chose à propos de l'arbre est que vous pouvez l'obtenir directement de l'analyseur. Si vous voulez le convertir en structures imbriquées, vous pouvez le faire, et cela pourrait rendre la navigation des structures imbriquées plus simples. Mais faire la conversion, vous devez marcher dans l'arbre de toute façon, vous avez déjà une navigation. Si vous accédez fortement aux structures imbriquées fortement, elles vont gagner en performance ... mais sûrement lors de la construction d'un assembleur que vous allez uniquement consulter chaque «champ» de l'instruction une fois.


Merci de votre réponse, cela clarifie quelque peu. Je pense que mon malentendu provient du fait que les assemblées que j'ai écrites ont mis en œuvre une analyse ad-hoc et que j'ai essayé d'appliquer votre explication au modèle mental pour l'analyse de cette manière. Il suffit de renforcer le fait que j'ai beaucoup à apprendre dans ce domaine.



3
votes

En réalité, les opcodes n'ont pas une base d'octets, mais une base octale. La meilleure description que je connaisse est Décodage Z80 OPCODES .


1 commentaires

Ya, juste sur. Octal vous permet de traduire directement et un appel récursif peut traiter avec les registres offset. On n'a pas besoin de construire un arbre de syntaxe du tout. Chaque instruction et être directement mappé.