Je lis le livre Les éléments des systèmes informatiques: Construire un ordinateur moderne à partir de Premiers principes , qui contient des projets englobant la construction d'un ordinateur, des portes booléennes aux applications de haut niveau (dans cet ordre). Le projet actuel sur lequel je travaille consiste à écrire un assembleur en utilisant un langage de haut niveau de mon choix, pour convertir du code d'assemblage Hack en code machine Hack (Hack est le nom de la plate-forme matérielle construite dans les chapitres précédents). Bien que le matériel ait été construit dans un simulateur, j'ai essayé de prétendre que je construisais réellement chaque niveau en utilisant uniquement les outils dont je disposais à ce stade du processus réel.
Cela dit, ça m'a fait réfléchir. Utiliser un langage de haut niveau pour écrire mon assembleur est certes pratique, mais pour le tout premier assembleur écrit (c’est-à-dire dans l’histoire), n’aurait-il pas besoin de l’écrire en code machine, c’est tout ce qui existait à l’époque?
Et une question corrélée ... et aujourd'hui? Si une nouvelle architecture de processeur, avec un tout nouveau jeu d'instructions et une toute nouvelle syntaxe d'assemblage, apparaît, comment l'assembleur sera-t-il construit? Je suppose que vous pouvez toujours utiliser un langage de haut niveau existant pour générer des fichiers binaires pour le programme assembleur, car si vous connaissez la syntaxe des langages assembleur et machine pour votre nouvelle plate-forme, alors la tâche d'écrire l'assembleur n'est vraiment qu'un travail. tâche d'analyse de texte et n'est pas intrinsèquement liée à cette plate-forme (c'est-à-dire qu'elle doit être écrite dans le langage machine de cette plate-forme) ... c'est la raison même pour laquelle je suis en mesure de "tricher" lors de l'écriture de mon assembleur Hack en 2012, et d'utiliser certains éléments préexistants. langue de haut niveau pour m'aider.
Réponses:
Pas nécessairement. Bien sûr, la toute première version v0.00 de l'assembleur doit avoir été écrite en code machine, mais elle ne serait pas suffisamment puissante pour être appelée un assembleur. Il ne prendrait même pas en charge la moitié des fonctionnalités d’un "vrai" assembleur, mais il suffirait d’écrire la version suivante. Ensuite, vous pouvez réécrire la version 0.00 dans le sous-ensemble du langage assembleur, appelez-la v0.01, utilisez-la pour créer le prochain jeu de fonctionnalités de votre assembleur v0.02, puis utilisez v0.02 pour construire v0.03 et ainsi de suite, jusqu'à ce que vous arriviez à v1.00. En conséquence, seule la première version sera en code machine; la première version publiée sera dans le langage d'assemblage.
J'ai démarré le développement d'un compilateur de langage de template en utilisant cette astuce. Ma version initiale utilisait des
printf
instructions, mais la première version que j'ai utilisée dans mon entreprise utilisait le processeur de modèle même qu'elle traitait. La phase de démarrage a duré moins de quatre heures: dès que mon processeur pouvait produire une sortie peu utile, je l'ai réécrit dans son propre langage, compilé, et jeté la version non modélisée.la source
diff
sur le générateur de code actuel pour vérifier que la partie générée du code n’a pas changé de manière inattendue, en remplaçant le code en place, et l'exécuter une fois de plus pour terminer le cycle.Selon Wikipedia, le tout premier langage d'assemblage / d'assemblage a été mis en œuvre pour IBM 701 par Nathaniel Rochester . (Les dates sont un peu incertaines de l’article de Wikipedia. Il est écrit que Rochester a rejoint IBM en 1948, mais une autre page de Wikipedia indique que le 701 a été annoncé publiquement en 1952. Et cette page d’IBM indique que "la conception réelle a débuté en février 1, 1951 et a été achevée un an plus tard " .)
Cependant, "assembleurs et chargeurs" de David Salomon indique (à la page 7) qu'EDSAC avait également un assembleur:
En supposant que nous acceptions la priorité des "ordres initiaux", nous avons la preuve évidente que le premier assembleur été implémenté dans le code machine.
Ce modèle (écrire les assembleurs initiaux dans le code machine) aurait été la norme jusque dans les années 1950. Toutefois, selon Wikipedia , "les assembleurs ont été les premiers outils linguistiques à se lancer eux-mêmes". Voir aussi cette section qui explique comment un code machine écrit par un assembleur primordial a été utilisé pour démarrer un assembleur plus avancé codé en langage assembleur.
De nos jours, les assembleurs et les compilateurs sont écrits dans des langages de niveau supérieur, et un assembleur ou un compilateur pour une nouvelle architecture de machine est généralement développé sur une architecture différente et compilé de manière croisée.
(FWIW - l'écriture et le débogage de programmes non triviaux dans le code machine est un processus extrêmement laborieux. Quelqu'un développant un assembleur en code machine amorcerait très probablement un assembleur écrit en assembleur dès que possible.)
Cette page Wikipedia sur l’ amorçage des compilateurs et des assembleurs vaut la peine d’être lue ... si cela vous déroute.
la source
Je présume que les premiers assembleurs ont été écrits en code machine, car comme vous le dites, rien d’autre n’était disponible à l’époque.
Aujourd'hui, cependant, quand une toute nouvelle architecture de processeur sort, nous utilisons ce que l'on appelle un compilateur croisé. , qui est un compilateur qui produit un code machine non pas pour l'architecture sur laquelle il s'exécute, mais pour une architecture différente.
(En fait, comme je suis sûr que vous le découvrirez plus tard dans le livre que vous lisez, rien ne permet absolument de rendre un compilateur plus apte à produire du code machine pour l’architecture sur laquelle il est exécuté. l’architecture que vous allez cibler, en tant que créateur du compilateur).
Ainsi, aujourd’hui, il est même possible (au moins en théorie) de créer une toute nouvelle architecture et d’avoir des compilateurs de langage de haut niveau fonctionnant en mode natif (compilé sur d’autres architectures utilisant des compilateurs croisés) avant même de disposer d’un assembleur pour cette architecture.
la source
Au début, "assemblage" était écrit sur papier, puis "compilé" manuellement sur des cartes perforées.
Mon grand-père travaillait avec une ZRA1 (désolée, la page n’existe qu’en allemand, mais la traduction de Google est satisfaisante au point de vous permettre de relever les faits les plus importants: D).
Le modus operandi consistait à écrire votre code sur papier dans une sorte de langage d'assemblage et la secrétaire se chargerait de la transcription pour perforer les cartes, puis les transmettrait à l'opérateur et le résultat serait rendu le lendemain matin.
Tout cela était essentiellement avant que les programmeurs aient le luxe de saisir des données à l'aide d'un clavier et de les visualiser sur un écran.
la source
Il est difficile d'être certain de la très premier assembleur (difficile de définir ce que c'était). Il y a des années, lorsque j'ai écrit quelques assembleurs pour des machines dépourvues d'assembleurs, j'ai quand même écrit le code en langage assembleur. Ensuite, après avoir eu une section de code assez complète, je l'ai traduite manuellement en code machine. C'étaient toujours deux phases totalement distinctes: lorsque j'écrivais le code, je ne travaillais pas ou ne pensais pas du tout au niveau du code machine.
J'ajouterais que dans quelques cas, j'ai même progressé: j'ai écrit la plupart du code dans un langage d'assemblage que je trouvais plus simple à utiliser, puis j'ai écrit un petit noyau (plus ou moins ce que nous appellerions maintenant une machine virtuelle). pour interpréter cela sur le processeur cible. C'était extrêmement lent (surtout sur un processeur 8 MHz), mais cela importait peu, car il ne fonctionnait normalement qu'une fois (ou tout au plus, quelques fois).
la source
Vous n'avez pas besoin d'un assembleur pour assembler à la main le code de langage d'assemblage en code machine. Tout comme vous n'avez pas besoin d'un éditeur pour écrire du code en langage assembleur.
Une perspective historique
Les premiers assembleurs ont probablement été écrits en langage d'assemblage, puis assemblés à la main en code machine. Même si le processeur n'avait pas de «langage d'assemblage» officiel, les programmeurs avaient probablement presque tout le travail de programmation en utilisant une sorte de pseudo-code avant de le traduire en instructions machine.
Même au tout début de l'informatique , les programmeurs écrivaient des programmes avec une sorte de notation symbolique et les traduisaient en code machine avant de l'insérer dans leur ordinateur. Dans le cas d’Augusta Ada King, elle aurait dû les traduire en cartes perforées pour le moteur analytique de Babbage , mais hélas cela n’a jamais été construit.
Expérience personnelle
Le premier ordinateur que j'ai possédé était un Sinclair ZX81 (Timex 1000 aux États-Unis). Au verso du manuel, vous trouverez toutes les informations nécessaires pour traduire le langage d'assemblage du Z80 en code machine (même en incluant tous les opcodes bizarres du mode index du Z80).
J'écrirais un programme (sur papier) en langage d'assemblage et essaierais le code. Lorsque j'étais heureux de constater que mon programme ne contenait aucun bogue, je parcourais chaque instruction au verso du manuel, le traduisais en code machine et notais le code machine sur le papier. Enfin, je taperais toutes les instructions du code machine dans mon ZX81 avant de l’enregistrer sur une bande et de l’essayer.
Si cela ne fonctionnait pas, je vérifiais de nouveau mon assemblage manuel et, si une traduction était fausse, je corrigeais les octets chargés sur la bande avant de la réenregistrer et d'essayer à nouveau de lancer le programme.
Par expérience, je peux vous dire qu'il est beaucoup plus facile de déboguer votre code s'il est écrit en langage assembleur que dans le code machine - d'où la popularité des désassembleurs. Même si vous n'avez pas d'assembleur, l'assemblage manuel est moins sujet aux erreurs que d'essayer d'écrire directement du code machine, même si je suppose qu'un vrai programmeur comme Mel pourrait ne pas être d'accord. * 8 ')
la source
Il n'y a pas de différence alors ou maintenant. Vous voulez inventer un nouveau langage de programmation, vous choisissez l’un des langages à votre disposition aujourd’hui pour faire le premier compilateur. sur un certain temps, s'il s'agit d'un objectif du projet, vous créez un compilateur dans ce langage, qui peut alors s'auto-héberger.
Si vous n'aviez que du crayon et du papier et quelques commutateurs ou cartes perforées comme interface utilisateur pour le premier ou le prochain jeu d'instructions, vous avez utilisé un ou tous les éléments à votre disposition. Vous auriez très bien pu écrire un langage d'assemblage, sur papier, puis utiliser un assembleur, vous, pour le convertir en code machine, peut-être en octal, puis à un moment donné dans l'interface de la machine.
Quand un tout nouveau jeu d’instructions est inventé aujourd’hui, cela n’est pas différent, en fonction de la société / des individus, des pratiques, etc., il est fort probable que l’ingénieur en matériel programmant probablement en verilog ou en vhdl écrit les premiers programmes de test manuellement en code machine (probablement en hexadécimal ou binaire). En fonction des progrès réalisés par les équipes logicielles, celles-ci peuvent très rapidement ou non passer à un langage d'assemblage, puis à un compilateur.
Les premières machines informatiques n'étaient pas des machines d'usage général pour créer des assembleurs et des compilateurs. Vous les avez programmées en déplaçant des fils entre la sortie de l'alu précédent et l'entrée du suivant. Finalement, vous avez eu un processeur généraliste permettant d'écrire un assembleur en assembleur, de l'assembler à la main, de le nourrir en tant que code machine, puis de l'utiliser pour analyser ebcdic, ascii, etc., puis de s'auto-héberger. stockez le fichier binaire sur un support que vous pourriez lire / charger ultérieurement sans avoir à continuer à basculer les commutateurs pour alimenter manuellement le code machine.
Pensez aux cartes perforées et au ruban adhésif. Au lieu de basculer les commutateurs, vous pouvez très certainement créer une machine entièrement mécanique, un dispositif permettant d'économiser du travail, qui crée le support lu par l'ordinateur. Au lieu de devoir saisir les bits de code machine avec des commutateurs comme un altair, vous pouvez utiliser du ruban de papier ou des cartes perforées (en utilisant quelque chose de mécanique, non pilotée par processeur, qui alimentait la mémoire ou le processeur, OU en utilisant un chargeur de démarrage écrit avec un petit code machine). Ce n’était pas une mauvaise idée, car vous pouviez créer quelque chose, piloté par l’ordinateur, capable également de produire mécaniquement les bandes de papier ou les cartes perforées, puis de les réintroduire. Deux sources de cartes perforées, le dispositif permettant d’économiser de la main-d’œuvre mécanique et la machine pilotée par ordinateur. les deux produisent les "binaires" pour l'ordinateur.
la source
Il y a un ou deux cas dans le zoo informatique de Brook où il a dit quelque chose comme "les mnémoniques sont notre invention, le concepteur a simplement utilisé l'opcode numérique ou le caractère dont le code était l'opcode", de sorte qu'il existe des machines pour lesquelles il n'y a même pas langage d'assemblage.
La saisie de programmes met fin au débogage sur le panneau avant (pour ceux qui ne l’avaient pas encore fait, c’était une façon de configurer la mémoire, vous définissiez certains commutateurs sur l’adresse, d’autres sur la valeur et appuyez sur un bouton ou sur un autre lire la valeur) était commun bien plus tard. Certains anciens se vantent de pouvoir encore entrer le code de démarrage des machines qu’ils utilisent beaucoup.
La difficulté d'écrire directement le code machine et de lire les programmes à partir de la mémoire mémoire dépend du langage de la machine. Certaines sont relativement faciles (le plus difficile est de suivre les adresses), x86 est l'un des pires.
la source
J'ai construit un ordinateur en 1975. Il était très avancé par rapport à l'Altair contemporain, car il disposait d'une "rom de moniteur" qui me permettait d'entrer dans des programmes en tapant le code machine au format hexadécimal et en visualisant ce code sur un moniteur vidéo. Altair chaque instruction machine a dû être entré un bit à la fois en utilisant une rangée de commutateurs.
Donc, oui, au début des ordinateurs et encore une fois aux ordinateurs personnels, les gens écrivaient des applications en code machine.
la source
Une anecdote:
Quand j’ai appris le langage assembleur sur Apple] [, il y avait un programme inclus dans la ROM appelé le micro-assembleur. Il a immédiatement traduit l'instruction d'assemblage en octets, comme vous les avez entrées. Cela signifie qu'il n'y avait pas d'étiquettes - si vous voulez sauter ou charger, vous devez calculer vous-même les compensations. C'était beaucoup plus facile que de regarder les schémas d'instructions et d'entrer des valeurs hexadécimales.
Nul doute que les vrais assembleurs ont d’abord été écrits en utilisant le micro-assembleur, ou un autre environnement peu complet.
la source