2013-04-13 2 views
9

J'ai récemment essayé de me plonger dans le monde de la programmation d'assemblage avec l'objectif final de créer mon propre langage de programmation. Je veux que mon premier projet réel soit un simple assembleur écrit en C qui sera capable d'assembler une très petite partie du langage machine x86 et de créer un exécutable Windows. Pas de macros, pas de linkers. Juste l'assemblage.Je veux créer un simple assembleur en C. Où devrais-je commencer?

Sur le papier, cela semble assez simple. Le code d'assemblage entre, le code machine sort.

Mais dès que je pense à tous les détails, tout devient soudain très décourageant. Quelles conventions le système d'exploitation exige-t-il? Comment aligner les données et calculer les sauts? À quoi ressemble l'intérieur d'un exécutable?

Je me sens perdu. Il n'y a pas de tutoriel sur ce sujet que je pourrais trouver et regarder le code source des assembleurs populaires n'était pas inspirant (je suis prêt à essayer à nouveau, cependant).

Où puis-je aller? Comment l'auriez-vous fait? Y a-t-il de bons tutoriels ou de la littérature sur ce sujet?

+1

Quelque chose à penser: Automate fini pour vérifier si l'utilisateur utilise même les instructions appropriées, et vous aurez également besoin d'un analyseur pour vous assurer que ce que le programmeur écrit est correct. Bien qu'il y ait beaucoup de choses sur le système, vous devrez vous inquiéter, il y a aussi beaucoup de théorie de calcul que vous devrez également connaître. –

+1

Peut-être que vous devriez étudier un paquet comme [NASM] (http://www.nasm.us/). –

+0

vérifier [ce défi sur le golf de code] (http://codegolf.stackexchange.com/questions/4732/emulate-an-intel-8086-cpu) pour les ressources 8086 et un exemple de programme pas trop court en utilisant un sous-ensemble de 8086 dans les deux formes source et binaire. OMI, le Manuel de 1979 est le point de départ. ... Jetez aussi un coup d'œil à [la question de mon wiki sur les ressources de l'assemblée] (http://stackoverflow.com/a/7203667/), en particulier le fichier "PDP-1_Macro.pdf" qui donne une description détaillée d'un assembleur très primitif . –

Répondre

3

Ce que vous cherchez n'est pas un tutoriel ou un code source, c'est une spécification . Voir http://msdn.microsoft.com/en-us/library/windows/hardware/gg463119.aspx

Une fois que vous avez compris la spécification d'un exécutable, écrivez un programme pour en générer un. L'exécutable que vous construisez doit être aussi simple que possible. Une fois que vous avez maîtrisé cela, puis vous pouvez écrire un analyseur orienté ligne simple qui lit les noms d'instruction et les arguments numériques pour générer un bloc de code à brancher sur l'exe. Plus tard, vous pouvez ajouter des symboles, des branches, des sections, ce que vous voulez, et c'est là que quelque chose comme http://www.davidsalomon.name/assem.advertis/asl.pdf viendra po

P.S. Carl Norum a un bon point dans le commentaire ci-dessus. Si votre but est de créer votre propre langage de programmation, apprendre à écrire un assembleur n'est pas pertinent et n'est pas vraiment la bonne façon de commencer (à moins que le langage que vous voulez créer soit un langage assembleur). Il y a déjà des assembleurs qui produisent des exécutables à partir de la source de l'assembleur, donc votre compilateur pourrait produire la source de l'assembleur et vous pourriez éviter le travail de recréer l'assembleur ... et vous devriez. Ou vous pourriez utiliser quelque chose comme LLVM, qui résoudra beaucoup d'autres problèmes décourageants de la construction du compilateur. Les probabilités sont très minimes que vous produisiez votre propre langage de programmation, mais ils sont beaucoup plus petits si vous recommencez à zéro et que vous n'avez pas besoin de le faire. Décidez de votre objectif et utilisez les meilleurs outils disponibles pour l'atteindre.

4

Vous devriez regarder LLVM, llvm est un back-end de compilateur modulaire, le frontal le plus populaire est Clang pour compiler C/C++/Objective-C. La bonne chose à propos de LLVM est que vous pouvez choisir la partie de la chaîne du compilateur qui vous intéresse et vous concentrer sur cela, en ignorant tous les autres. Vous voulez créer votre propre langage, écrire un analyseur qui génère le code de représentation interne LLVM, et vous obtenez gratuitement toutes les optimisations indépendantes de la couche intermédiaire et la compilation vers de nombreuses cibles différentes. Intéressant dans un compilateur pour certains CPU exotiques, écrivez un backend de compilateur qui prend le code intermédiaire LLVM et génère votre assemblage. Avoir quelques idées sur les techniques d'optimisation, threading automatique peut-être, écrire une couche intermédiaire qui traite le code intermédiaire LLVM. LLVM est une collection de bibliothèques qui n'est pas un binaire autonome comme GCC, et est donc très facile à utiliser dans vos propres projets.

11

J'ai moi-même écrit quelques-uns (assembleurs et désassembleurs) et je ne voudrais pas commencer par x86. Si vous connaissez x86 ou tout autre jeu d'instructions, vous pouvez récupérer et apprendre rapidement la syntaxe d'un autre jeu d'instructions (une soirée/après-midi), au moins la part des lions.Le fait d'écrire un assembleur (ou un désassembleur) vous apprendra certainement un ensemble d'instructions, et vous saurez que l'ensemble d'instructions est meilleur que de nombreux programmeurs chevronnés pour cet ensemble d'instructions qui n'ont pas examiné le microcode à ce niveau. msp430, pdp11, et le pouce (pas les extensions thumb2) (ou mips ou openrisc) sont tous de bons endroits pour commencer, pas beaucoup d'instructions, pas trop compliqué, etc.

Je recommande d'abord un désassembleur, et avec cela un Si ce n'est pas le cas, utilisez au moins un désassembleur (choisissez certainement un jeu d'instructions pour lequel vous avez déjà un assembleur, un éditeur de liens et un désassembleur) et avec un crayon et du papier, comprenez la relation entre le code machine et l'assemblage, en particulier les branches, ils ont généralement une ou plusieurs bizarreries comme le compteur de programme est une instruction ou deux en avant lorsque le décalage est ajouté, pour gagner un autre bit qu'ils mesurent parfois en instructions entières et non en octets.

Il est assez facile de force brute analyser le texte avec un programme C pour lire les instructions. Une tâche plus difficile mais peut-être aussi éducative serait d'utiliser bison/flex et d'apprendre ce langage de programmation pour permettre à ces outils de créer un analyseur syntaxique encore plus extrême qui s'interface alors avec votre code pour vous dire ce qui a été trouvé.

L'assembleur lui-même est assez simple, il suffit de lire les caractères ASCII et de définir les bits dans le code machine. Les branchements et autres instructions relatives aux pc sont un peu plus douloureux car ils peuvent prendre plusieurs passages à travers la source/les tables pour les résoudre complètement.

mov r0,r1 
    mov r2 ,#1 

l'assembleur commence l'analyse du texte pour une ligne (étant définie comme les octets qui suivent un flux 0xA retour chariot 0xD ou ligne), jeter l'espace blanc (espaces et onglets) jusqu'à ce que vous obtenez à quelque chose non blanc espace, puis strncmp qu'avec les mnémoniques connus. si vous en frappez un, alors analysez les combinaisons possibles de cette instruction, dans le cas simple ci-dessus après le saut de l'espace blanc vers un espace non-blanc, peut-être que la première chose que vous trouverez doit être un registre, puis un espace blanc virgule. Enlevez les espaces et les virgules et comparez-les à une table de chaînes ou passez-la à l'analyse. Une fois que ce registre est fait, passez la case où la virgule est trouvée et disons que c'est soit un autre registre, soit un immédiat. Si immédiat, disons qu'il doit avoir un signe #, si le registre indique qu'il doit commencer par un 'r' minuscule ou majuscule. après l'analyse de ce registre ou immédiatement, alors assurez-vous qu'il n'y a rien d'autre sur la ligne qui ne devrait pas être sur la ligne. Construire le code machine pour cette instruction ou au moins autant que possible, et passer à la ligne suivante. Il peut être fastidieux, mais il est difficile de ne pas analyser ascii ...

au minimum, vous voulez une table/tableau qui accumule le code machine/données est créé, plus une méthode pour obtenir des instructions de marquage comme étant incomplet , les instructions pc-relatives à compléter sur une future passe. vous voudrez également une table/tableau qui recueille les étiquettes que vous trouvez et l'adresse/décalage dans la table de code machine où trouvé. Ainsi que les étiquettes utilisées dans l'instruction comme une destination/source et le décalage dans la table/tableau contenant l'instruction partiellement complète qu'ils vont avec. après le premier passage, retournez dans ces tables jusqu'à ce que vous ayez fait correspondre toutes les définitions d'étiquette avec les étiquettes utilisées comme source ou destination, en utilisant l'adresse/l'offset de définition d'étiquette pour calculer la distance à l'instruction en question et terminez la création le code machine pour cette instruction. (un démontage peut être nécessaire et/ou utiliser une autre méthode pour se souvenir du type d'encodage lorsque vous y reviendrez plus tard pour terminer la construction du code machine).

L'étape suivante consiste à autoriser plusieurs fichiers sources, si c'est quelque chose que vous voulez autoriser. Maintenant vous devez avoir des étiquettes qui ne sont pas résolues par l'assembleur, vous devez donc laisser des espaces réservés dans la sortie et faire la plus longue des instructions de saut/branchement parce que vous ne savez pas à quelle distance se trouvera la destination.Ensuite, il y a le format de fichier de sortie que vous choisissez de créer/utiliser, puis il y a le lieur qui est pour la plupart simple, mais vous devez vous rappeler de remplir le code machine pour les instructions relatives au pc final, pas plus dur que dans l'assembleur lui-même. Remarque, l'écriture d'un assembleur n'est pas nécessairement liée à la création d'un langage de programmation, puis l'écriture d'un compilateur pour lui, chose distincte, différents problèmes. En fait, si vous voulez créer un nouveau langage de programmation, utilisez simplement un assembleur existant pour un jeu d'instructions existant. Non requis bien sûr, mais la plupart des enseignements et des tutoriels vont utiliser l'approche bison/flex pour les langages de programmation, et il existe de nombreuses notes de cours/ressources pour commencer les classes de compilateur que vous pouvez utiliser pour commencer, puis modifier le script pour ajouter les fonctionnalités de votre langue. Le milieu et le dos sont le plus grand défi que l'extrémité avant. Il existe de nombreux livres sur ce sujet et de nombreuses ressources en ligne. Comme mentionné dans une autre réponse llvm n'est pas un mauvais endroit pour créer un nouveau langage de programmation le milieu et les backends sont faits pour vous, vous avez seulement besoin de se concentrer sur le langage de programmation lui-même, le frontal.

Questions connexes