Développement du langage adaptatif PARADISE du système de programmation de dialogue DSSP Moskovsky Université d'État Faculté de mathématiques computationnelles et cybernétique N.P. Brussentsov, V. B. Zakharov, I. A. Rudnev, S. A. Sidorov, N. A. Chanyshev Moscou, 1987
Description générale du langage de PARADISE
But et but du développement du langage
PARADISE (Developable Adaptive Language) est le langage de base du système de dialogue de programmation structurée DSPP. Basique signifie qu'il est à la base de toutes les constructions ultérieures réalisées dans le DSSP en développant (élargissant, renforçant) le langage de base et, éventuellement, en adaptant les moyens linguistiques ainsi créés à une application spécifique. Contrairement aux langages dits de haut niveau, PARADIS ne fournit pas de types de données et d'opérations toutes faites, mais uniquement des éléments et des primitives pour définir efficacement les types requis. Par exemple, les formats de données d'origine sont des octets de 8 bits, des mots de 16 bits et des mots de 32 bits, interprétés en fonction des opérations effectuées sur eux comme des entiers, des vecteurs booléens, des codes de lettres, des booléens, des pointeurs de données et de procédure. Dans ce cas, il est possible, d'une part, de manipuler des bits individuels d'octets et de mots, et d'autre part, de former des unités de données composites (mots de longueurs multiples, vecteurs, tableaux, chaînes de texte, etc.), réglage pour eux l'une ou l'autre interprétation introduction d'opérations appropriées. Ainsi, des nombres réels de la longueur et de la plage de valeurs requises, des nombres complexes et d'autres objets peuvent être introduits, et la version du langage orientée vers une application donnée inclura des objets et des moyens inhérents à cette application et n'inclura rien qui ne s'y appliquent - la langue sera adaptée (adaptée) à l'application. Le développement du DSPP visait à créer un outil largement disponible et recours efficace programmation sur micro-ordinateur, c'est-à-dire ordinateurs basés sur des microprocesseurs. Une caractéristique essentielle de l'architecture des microprocesseurs est la nature élémentaire des types de données et des opérations, ce qui signifie, d'une part, l'universalité, et d'autre part, la pénibilité de la programmation. En raison de leur polyvalence, les microprocesseurs et les micro-ordinateurs créés sur leur base ont des possibilités d'application potentiellement illimitées. Cependant, la mise en œuvre pratique de ces capacités repose principalement sur la pénibilité du développement des programmes d'application requis. De plus, des programmes d'application satisfaisants ne peuvent être créés qu'avec une connaissance approfondie et subtile des spécificités des applications respectives, c'est-à-dire ils devraient être développés non seulement par des programmeurs, mais par des spécialistes hautement qualifiés dans un domaine ou un autre. Par conséquent, le système de programmation doit non seulement augmenter considérablement la productivité du travail du programmeur, mais aussi être si simple qu'il peut être maîtrisé et utilisé efficacement par des programmeurs non professionnels.
Une solution radicale à ce problème semblerait être une simplification significative de l'architecture informatique. Mais, malheureusement, l'architecture des micro-ordinateurs évolue dans une direction diamétralement opposée - sur la voie d'une complexité et d'une sophistication croissantes, de sorte qu'il n'est pas facile pour un programmeur professionnel de maîtriser parfaitement le langage d'un assembleur de micro-ordinateurs aujourd'hui. Les langages de programmation de systèmes tels que C ou PL/M ont, dans une certaine mesure (bien que loin d'être suffisant), réduit la complexité du développement de programmes, mais ils peuvent difficilement être recommandés aux personnes qui n'ont pas d'expérience dans le métier de la programmation. Un langage largement disponible devrait, bien sûr, être plus simple et plus naturel, devrait être basé, dans la mesure du possible, sur des idées ordinaires et familières concernant l'essence et la technique de la programmation.
En plus de la disponibilité et d'une réduction significative de la complexité de développement du programme par rapport à la programmation en langage assembleur, le DSPP nécessitait la polyvalence du langage, la même que celle du langage assembleur, un rendement machine élevé (c'est-à-dire la compacité et la rapidité du code), la fiabilité de la testabilité des programmes créés, et leur maintenabilité et modifiabilité, ainsi que la mobilité (portabilité) du système et des programmes qui y sont développés vers des machines d'architectures différentes.
Programmation procédurale
La programmation dans le langage de PARADISE est assez similaire à des types d'activités humaines aussi répandus que la planification et l'organisation d'actions, de travaux, de processus interdépendants ou la construction d'objets matériels complexes - machines, unités, structures. Tel un concepteur réalisant son idée en agrégeant ses éléments constitutifs (blocs, assemblages, pièces), le programmeur synthétise l'action complexe requise à partir des actions simples fournies par le langage. Nous pouvons également dire que la programmation (conception) est la décomposition progressive (décomposition) de l'objet mis en œuvre en composants de plus en plus petits.
Dans le langage de PARADISE, le principal "construit" est une procédure - une action nommée. Le langage est basé sur un ensemble limité des procédures les plus simples (primitives), représentées par leurs propres noms (désignations). Par exemple : + signifie ajouter, NEG signifie changer de signe, VCTR signifie créer un vecteur. En particulier, il existe des primitives : et ; (deux points et point-virgule), vous permettant de saisir une nouvelle procédure, par exemple, avec le nom P, en la définissant comme une séquence de procédures P1, P2, ..., PN sous la forme
: P P1 P2 ... PN;
Si la procédure P représente l'action que doit effectuer le programme créé, la construction de ce programme au moyen du langage PARADISE se réduit au détaillage séquentiel des procédures P1, P2, ..., PN. Cela signifie que chacune de ces procédures doit être définie par une séquence de procédures plus petites, qui sont ensuite définies par des séquences de procédures encore plus petites, et ainsi de suite, jusqu'à ce que des définitions constituées uniquement de primitives soient obtenues.
Cette conception d'un programme, partant d'une cible donnée et réduisant progressivement les procédures qu'il utilise au cœur du langage, est connue sous le nom de programmation descendante. C'est le principal moyen d'obtenir des programmes dans le langage PARADISE pour résoudre des problèmes individuels bien définis. Le contraire est la programmation ascendante - la construction d'un système de procédures progressivement élargies basé sur les moyens de base du langage, concentré sur un certain domaine problématique. De cette façon, le développement du langage et son adaptation à une application spécifique est réalisé.
Dans les deux cas, une structuration approfondie des programmes créés est indispensable : chaque programme et chaque partie d'un programme doit être constitué d'un petit nombre de parties distinctes, dont chacune remplit une fonction spécifique et permet une vérification autonome. En ce qui concerne le langage de PARADISE, cela signifie notamment que les définitions des procédures doivent être courtes : la séquence de définition, en règle générale, ne doit pas contenir plus de 5 à 7 membres. La structuration apporte clarté, vérifiabilité et modifiabilité du programme, réduit considérablement la complexité de sa création et de sa maintenance.
L'exemple ci-dessus de définition de la procédure P est simplifié. En fait, la séquence de définition peut contenir comme membres non seulement les noms de procédures, mais également des instructions (commandes) constituées de plus d'un mot. Un nom de procédure, lorsqu'il est utilisé en dehors de la combinaison avec d'autres mots, est une commande pour exécuter la procédure désignée par celui-ci. La séquence des noms de procédures dicte l'exécution de ces procédures dans l'ordre de leurs noms les unes après les autres (dans l'ordre linéaire). Pour spécifier d'autres séquences d'exécution, PARADISE fournit des mots spéciaux (préfixes) qui prescrivent l'exécution des procédures nommées en combinaison avec eux, en fonction de la condition spécifiée, ainsi que l'exécution répétée (cyclique) de la procédure.
Par exemple, une séquence linéaire P0 P1 provoque l'exécution de la procédure P0 puis l'exécution de la procédure P1. Si la procédure P1 ne doit pas toujours être exécutée, mais plutôt s'il est prévu qu'à la suite de l'exécution de P0 un nombre positif est obtenu, alors au lieu de P1, ils écrivent la commande d'exécution selon la condition : IF + P1, c'est-à-dire au lieu de P0 P1 il y aura P0 IF + P1. PARADISE inclut un ensemble de conditions de préfixe qui vous permettent d'exprimer efficacement l'exécution conditionnelle, ainsi qu'un choix de deux, trois procédures ou plus.
L'exécution multiple de la procédure est spécifiée à l'aide du préfixe RP. Ainsi, la commande RP P appelle l'exécution de la procédure P encore et encore jusqu'à ce que les conditions soient créées dans lesquelles l'EX contenu dans le corps de cette procédure est déclenché - sortie de la boucle, après quoi la commande suivante dans l'ordre linéaire est exécutée . La condition de sortie de la boucle peut être, par exemple, l'égalité à zéro d'une variable X, qui s'exprime ainsi :
Une procédure dont le nom apparaît dans la définition d'une autre procédure est dite imbriquée en son sein. Une procédure imbriquée, si ce n'est pas une primitive, peut à son tour contenir des procédures imbriquées, c'est-à-dire l'imbrication peut être multiple. De plus, les règles du langage PARADISE n'interdisent pas l'inclusion dans la définition d'une procédure de son propre nom ou du nom d'une procédure contenant ce nom, c'est-à-dire PARADISE permet la récursivité.
Une procédure exécutée de manière répétée peut également être imbriquée dans une procédure exécutée de manière répétée. Dans ce cas, les boucles sont imbriquées. PARADISE permet de multiples imbrications de boucles.
Séquence linéaire de commandes, imbrication, imbrication conditionnelle et cyclique de procédures - cela épuise les possibilités de construction de programmes dans le langage PARADISE. La rareté, l'homogénéité et le naturel de ces moyens sont un gage de facilité de maîtrise et d'utilisation de la langue. Dans le même temps, il s'agit d'un langage de programmation structuré et rigoureux qui permet une réduction significative de l'intensité du travail de développement et de la fiabilité du programme.
Procédures et données
Tout ce qui a été dit jusqu'ici est une caractéristique du langage de PARADISE comme moyen de prescrire des actions, de construire des actions arbitraires à partir d'un ensemble fini d'opérations primitives. L'envers du langage est constitué par les moyens de représenter des objets sur lesquels le actions, - signifie présentation et organisation des données.
Tout à fait élément simple les données sont un élément à deux chiffres - un peu. Tous les autres formats et types de données sont construits à partir de bits. Dans le langage PARADISE, les octets 8 bits, les mots 16 bits et les mots longs 32 bits sont acceptés comme formats de base. Selon les opérations effectuées sur eux, les octets, les mots et les mots longs admettent de nombreuses interprétations, c'est-à-dire peut servir de base à différents types Les données. Ils sont également le point de départ de la formation de formats et de types composites.
En réalité, PARADISE ne contient pas de types de données simples ou composites - il n'y a que des formats de base (octet, mot, mot long) et des moyens pour construire des formats composites à partir d'eux : des vecteurs et des tableaux multidimensionnels. Dans ce cas, les mêmes octets (mots, mots longs), selon les opérations effectuées sur eux, sont interprétés comme des vecteurs de bits, ou comme des entiers binaires avec et sans signe, ou comme des lettres de l'alphabet d'entrée/sortie, etc. . Les types de données et leurs contraintes et vérifications associées peuvent être introduits dans des extensions de langage orientées problèmes.
Dans le langage de base, la déclaration des noms de données n'a pour fonction que de donner accès aux données par leur nom : le nom est associé au nombre de cellules mémoire requises par la déclaration et au mécanisme d'accès à celles-ci. Les opérations de test et de transformation ne sont pas directement appliquées aux données nommées. Ces opérations sont définies sur la pile d'opérandes, qui est une séquence de mots de 32 bits (éléments de pile) modifiés dynamiquement en ajoutant (poussant) de nouveaux éléments à sa fin, ainsi qu'en supprimant des éléments de la même extrémité (sautant de la pile ). Les éléments sont retirés dans l'ordre inverse de celui dans lequel ils ont été envoyés : ce qui a été envoyé par le dernier est retiré en premier. Les données à tester ou à convertir sont poussées sur la pile, où les opérations prescrites sont effectuées dessus, après quoi les résultats du traitement peuvent être extraits de la pile.
Par exemple, s'il y a une variable X déclarée comme un mot long de 32 bits, alors seules deux opérations peuvent être effectuées directement dessus :
1) pousser sa valeur sur la pile, ce qui se produit automatiquement à chaque fois que le nom X est mentionné,
2) affectation à celui-ci par la commande ! La valeur X du dernier élément (en haut) sorti de la pile.
Si, par exemple, vous souhaitez doubler la valeur de X en l'ajoutant à lui-même, vous pouvez le faire en exécutant les commandes suivantes l'une après l'autre :
Deux copies de la valeur X seront poussées sur la pile, puis la commande + les fera apparaître, ajoutera et poussera le montant résultant sur la pile, après quoi la commande ! X supprimera ce montant et affectera sa valeur à la variable X.
La notation habituelle pour les langages de haut niveau de l'exemple donné sous la forme X: = X + X est plus familière au programmeur, mais ce n'est pas un reflet direct de la séquence d'instructions exécutée par le processeur, mais c'est un sorte de formule mathématique. Ceci est pratique lors de la programmation de tâches de calcul; cependant, dans le langage de base, une correspondance sans ambiguïté avec les commandes exécutées semble être plus importante, car le programme peut être vérifié par commande directement dans le langage de programmation et il n'est pas nécessaire de connaître un langage autre que le langage du processeur.
Mais un avantage particulièrement précieux du traitement des données empilées est que les routines de test et de transformation peuvent être définies et mises en œuvre indépendamment des données auxquelles elles sont appliquées. Les opérations de test et de transformation sont formulées non pas par rapport aux identifiants de données (ou noms de constantes et de variables, paramètres formels), mais par rapport aux éléments de la pile, auxquels doivent être affectées les valeurs des opérandes au moment de l'opération est effectuée. Par exemple, l'opération d'addition de deux nombres, effectuée par la commande + (ajouter), consiste à prendre les deux premiers éléments (top et sub) de la pile comme sommations, à calculer leur somme et à la pousser sur la pile. Pour ajouter deux nombres, vous devez pousser leurs valeurs sur la pile et exécuter la commande +, le résultat sera en haut de la pile.
Une procédure de test-transformation avec un nombre arbitraire de paramètres d'entrée et de sortie peut être définie de cette manière simplement comme une action nommée (sans liste de paramètres) effectuée sur la pile contenant les valeurs d'argument dans l'ordre prescrit, et après exécution - les valeurs des résultats. Pour appliquer une telle procédure à un ensemble particulier de données spécifiques, il est nécessaire de pousser ces données dans l'ordre approprié sur la pile. Après les avoir consommés, la procédure laissera ses résultats sur la pile (également disposés dans un certain ordre).
En d'autres termes, les noms de procédures dans le langage PARADISE sont utilisés de la même manière que les signes d'opérations et sont essentiellement des symboles d'opérations avec un nombre arbitraire d'opérandes. Conformément au principe de fonctionnement de la pile, les opérations sont écrites sous forme de suffixe, c'est-à-dire le nom de l'opération est placé après le listage des noms ou valeurs de ses opérandes. Par exemple, si vous désignez l'opération d'obtention de la somme de trois nombres par le symbole ++, alors la somme des nombres A, 5 et B s'exprimera comme suit :
Il serait possible d'établir des règles formelles d'un langage postfix et d'être guidé par elles lors de l'écriture de programmes, mais il est plus facile et plus sûr pour une personne de traiter non pas avec des règles, mais avec un modèle de processeur de pile, c'est-à-dire avec le modèle de la machine pour laquelle les programmes sont créés et qui les exécutera. Dans le cas du langage PARADISE, une telle machine est le processeur DSPP - un ensemble de matériel et de programmes qui implémentent les actions prescrites dans ce langage.
Processeur DSP
Physiquement, le processeur DSPP peut être implémenté sous la forme d'un microprocesseur à l'architecture simple et effectivement programmable qui résoudrait le problème d'équipement logiciel des micro-ordinateurs. la meilleure façon... Mais un tel microprocesseur n'a pas encore été créé et son architecture doit être émulée sur des micro-ordinateurs existants afin d'améliorer leur programmabilité. Bien sûr, l'émulation est coûteuse - elle nécessite de la mémoire et du temps machine pour l'implémenter, mais dans le cas de l'émulation d'un processeur PRSP, ces coûts sont relativement faibles.
Du point de vue du programmeur, la caractéristique d'un processeur est son architecture, c'est-à-dire informations sur ce qu'est un processeur donné en tant qu'outil de traitement de données, quelles sont les possibilités de présenter des données à l'entrée et à l'intérieur du processeur, quelles opérations de test et de conversion de données sont disponibles, comment la propre mémoire du processeur est organisée, ainsi que l'accès à la mémoire principale et externe, quels sont les contrôles le déroulement du programme, l'interaction avec environnement externe, réponse à des événements exceptionnels, etc. Maîtriser l'architecture revient à condition nécessaire programmation significative (informelle), qui réduit considérablement le nombre d'erreurs et augmente la fiabilité des programmes.
Le lien central du processeur DSPP est la pile d'opérandes susmentionnée. Dans la pile elle-même, le traitement est effectué et les données sont généralement transférées via la pile, en règle générale. Des commandes individuelles et de courtes séquences de commandes sur la pile peuvent être exécutées en les transmettant à l'entrée du processeur directement à partir du clavier du terminal. Dans ce cas, le processeur DSPP simule le fonctionnement d'un calculateur de suffixe. Les chiffres et codes mnémoniques des opérations saisies au clavier sont séparés par des espaces. Le texte saisi est affiché sous forme de chaîne sur l'écran du terminal. Le signal de fin d'entrée et la commande au processeur "Exécuter la prescription entrée" sont en appuyant sur la touche
Par exemple, pour calculer l'expression (2-5) * 3 et afficher le résultat, saisissez :
2 5 - 3 * .
Après avoir appuyé sur la touche
* 2 5 - 3 * . -90
Un astérisque au début d'une ligne est émis par le processeur comme signal qu'il attend une entrée.
Dans l'exemple considéré, le processeur a perçu et traité les nombres d'entrée comme des décimales entières. En fait, lors de la saisie, ces nombres ont été convertis en complément binaire et lors de la sortie, ils ont été reconvertis dans le système décimal. Le processeur PRSP permet également des modes d'E/S binaires, octaux et hexadécimaux. Pour passer au mode souhaité, l'une des commandes B2, B8, B10, B16 doit être respectivement exécutée.
L'appui sur les touches amène l'entrée du processeur à fournir des codes représentant les lettres indiquées sur ces touches (lettres, chiffres, signes de ponctuation, symboles d'opérations). La séquence de caractères d'entrée forme une chaîne d'entrée - une chaîne d'octets contenant les codes des caractères, un octet par caractère. La longueur maximale d'une chaîne d'entrée est de 80 caractères.
Lors du traitement de la chaîne d'entrée, le processeur y isole les mots - des combinaisons de lettres séparées les unes des autres par des espaces, et les interprète. Si le mot en cours de traitement est le nom d'une opération (procédure) ou d'une opération donnée, connue du processeur, alors le processeur effectue des actions qui doivent être appelées par ce nom par définition. Si le mot n'est pas connu du processeur, alors il essaie de l'interpréter comme un nombre, en tenant compte du mode E/S défini.
Les nombres sont reconnus comme des mots constitués de chiffres admissibles dans un système numérique donné et, peut-être, contenant un signe moins comme première lettre. Dans le mode d'entrée/sortie hexadécimal, les lettres latines A, B, C, D, E, F sont également valides, ainsi que des nombres. Le nombre reçu est converti en code de complément binaire et poussé sur la pile d'opérandes comme une longueur de 32 bits mot. Dans ce cas, si la valeur du nombre est en dehors de la plage de valeurs représentables -2147483648 : 2147483647, alors il est remplacé par une valeur comparable en module 2 ** 32 de cette plage.
Dans le cas où le mot traité n'est pas connu du processeur et ne peut être accepté comme numéro, le processeur affiche un message sur l'écran du terminal : « Je ne sais pas<обрабатываемое слово>" et attend que d'autres ordonnances soient saisies.
La saisie des données sous forme de texte libre (séquence d'octets-lettres) s'effectue sous forme de littéraux de texte, qui sont du texte entre guillemets doubles, par exemple : "Texte littéral". L'arrivée d'un littéral de texte en entrée du processeur provoque l'écriture du texte entre guillemets dans la mémoire principale sous la forme d'une chaîne de lettres d'octets. Dans ce cas, l'adresse du premier octet et le nombre d'octets (longueur du texte) sont poussés sur la pile. Un littéral de texte précédé d'un point est interprété par le processeur comme une commande pour "envoyer le texte entre les guillemets à l'écran du terminal". Par exemple, si vous fournissez la combinaison de symboles à l'entrée du processeur, « Pas de mémoire » fera apparaître le message : Pas de mémoire à l'écran.
Le code d'un caractère individuel est poussé sur la pile en tant qu'octet de poids faible du sommet lorsque ce caractère arrive à l'entrée du processeur avec le signe # qui lui est pré-envoyé. Par exemple, la combinaison de caractères #L enverra le code de la lettre L sur la pile, la combinaison de caractères # 5 enverra le code numéro 5. La commande TOB pour envoyer un octet au terminal affiche un caractère dont le code est contenu dans le bas octet du haut de la pile.
Même dans le mode d'exécution directe des commandes, le processeur PRSP surpasse de loin les capacités d'un calculateur conventionnel, offrant à l'utilisateur, en plus des opérations de traitement des données, les moyens de déclarer des données nommées et de définir des procédures qui peuvent ensuite être utilisées avec des opérations. Les noms de données sont déclarés et les procédures sont définies à l'aide de commandes spéciales.
Par exemple, pour créer une variable de 16 bits nommée, disons, TEMP, tapez sur le clavier et envoyez-la à l'entrée du processeur avec la touche
TEMP VAR
Vous pouvez affecter à une variable avec la déclaration valeur initiale par exemple 0 :
VAR TEMP 0 ! TEMPÉRATURE
Maintenant, l'arrivée du nom TEMP à l'entrée du processeur entraînera le push de la valeur actuelle de cette variable sur la pile, et l'affectation d'une nouvelle valeur extraite de la pile peut être effectuée par la commande ! TEMP.
Une définition de procédure est saisie par une commande : (deux points) contenant le nom de la procédure en cours de définition et définissant une chaîne de commande avec une lettre ; (point-virgule) comme caractère de fin de définition. Montrons la définition et l'utilisation des procédures par l'exemple du calcul de la factorielle d'un nombre naturel N par la formule
N! = N * (N-1) * (N-2) * ... * 2 * 1, c'est-à-dire Multiplication N-1.
La procédure FCT pour obtenir le résultat souhaité doit multiplier le nombre donné N par des nombres progressivement décroissants, en commençant de N-1 à 1, c'est-à-dire seulement N-1 fois. Dans le langage PARADISE, cela se programme par t fois l'exécution de la procédure P : DO P, où P est le nom de la procédure, t est la valeur courante du sommet de la pile, indiquant combien de fois la procédure P a besoin être éxecuté.
Supposons qu'avant l'application de la procédure FCT, le nombre N est poussé sur la pile et se trouve à son sommet. Pour rendre la procédure plus claire, nous représentons le multiplicateur modifiable de la variable K :
Nous introduisons la définition de la procédure FCT sous la forme :
FCT [N] ! K K K 1- FAIRE F. [N] ;
Les commentaires entre crochets reflètent l'état actuel de la pile d'opérandes. Équipe! K, par lequel débute la procédure définie, affecte la valeur du nombre N tiré de la pile à la variable K. Puis K est poussé deux fois sur la pile, et en soustrayant 1 en haut de la pile, le nombre d'exécutions de la procédure répétée F égale à N-1 est formée. Ceci est suivi par la commande DO F, qui prescrit une boucle, après laquelle le sommet de la pile contiendra la valeur factorielle requise - N !. Équipe. (point) imprime une copie de cette valeur sur l'écran du terminal. Il reste à définir la procédure F, qui modifie la valeur de K en soustrayant 1 et multiplie par K le résultat partiel du calcul de R. contenu dans la pile :
F [R] K 1-! K [R] K * ;
La vérification de l'exactitude des deux procédures est effectuée en exécutant leurs définitions une à la fois, en affichant le contenu de la pile d'opérandes et la valeur de la variable K sur l'écran du terminal après chaque commande. la pile doit contenir la valeur N !, et la valeur de la variable K doit être égale à 1.
Les procédures vérifiées et corrigées (si des erreurs ont été détectées lors du processus de vérification) sont testées en les appliquant à des valeurs individuelles du nombre N. La procédure F étant imbriquée dans le FCT, elle est testée automatiquement lors du dernier processus de test. Il faut garder à l'esprit que les valeurs du résultat ne doivent pas dépasser le nombre positif maximum représenté dans le code complément par un mot de 32 bits : 2147483647, c'est-à-dire Le FCT ne donne des résultats corrects que pour N = 1, ..., 13.
L'utilisation de FCT ne diffère pas de l'utilisation des propres instructions du processeur : pour obtenir le résultat, vous devez définir la valeur de l'opérande et saisir le nom de la procédure :
5 FCT
7 FCT
La mise en œuvre ci-dessus de la procédure FCT nécessitait l'introduction d'une variable auxiliaire K, cependant, une procédure fonctionnellement équivalente peut être effectuée sans variable auxiliaire en utilisant l'opération C, qui pousse une copie de son sommet sur la pile, et les opérations E2 et E3, qui échangent le sommet avec les deuxième et troisième éléments de la pile, respectivement. La définition de cette procédure est la suivante.
: FCTA [N] C 1- C DO FA D. ;
: FA C E3 * E2 1-;
L'avantage d'une telle procédure "purement stack" est sa totale autonomie : tout comme les opérations basiques de stack du processeur, elle s'effectue uniquement sur la pile d'opérandes, sans nécessiter d'autre mémoire et sans provoquer de changements dans les autres composants du processeur.
Les noms des procédures définies et les données déclarées sont entrés dans le dictionnaire du processeur, qui établit la connexion de ces noms avec les objets nommés, c'est-à-dire avec les corps de procédure situés dans la mémoire principale et avec les éléments de cette mémoire alloués à stocker les données déclarées. En traitant le mot suivant du flux d'entrée, le processeur parcourt le dictionnaire et, y trouvant un mot correspondant, exécute les actions associées à ce mot. Si la recherche a échoué, alors, comme déjà mentionné, une tentative est faite pour interpréter le mot numériquement, et si cela échoue, alors un message s'ensuit que le processeur ne connaît pas le mot.
À la suite de la compilation d'une définition de procédure, le nom de cette procédure et le pointeur (adresse) de son corps, qui est une séquence de pointeurs vers les procédures et les données qui composent la définition, sont entrés dans le dictionnaire. En d'autres termes, la représentation interne du corps de procédure est obtenue en remplaçant les noms de procédures et de données dans sa définition par les pointeurs des corps correspondants, qui sont à leur tour les mêmes séquences de pointeurs, et dans le cas des primitives, des chaînes des instructions de la machine. Nous appelons cette représentation interne du programme code procédural.
Lorsque, parallèlement à la compilation des définitions de la procédure P, les définitions de toutes les procédures imbriquées jusque-là inconnues du processeur sont compilées, une hiérarchie complète de pointeurs est formée qui permet d'exécuter la procédure P en ne fournissant que son nom à l'entrée du processeur. Dans ce cas, les noms des procédures imbriquées compilées en lien avec la définition de P, si vous n'avez pas besoin de vous référer à ces procédures séparément, cela n'a aucun sens de les stocker dans le dictionnaire. Dans un certain nombre de cas, il s'avère judicieux de fermer l'accès à l'une ou l'autre partie du dictionnaire, laissant peut-être la possibilité d'effectuer uniquement certaines procédures.
Afin de répondre à ces exigences, le dictionnaire est implémenté comme une collection de sous-dictionnaires, sur lesquels sont définies des opérations qui vous permettent de créer et de détruire des sous-dictionnaires et leurs parties, de supprimer des noms, de fermer et d'ouvrir l'accès à certains sous-dictionnaires. . Chaque sous-dictionnaire a un nom qui est utilisé dans les commandes qui lui sont associées. Les noms de sous-dictionnaires doivent commencer par $, par exemple : $ PRIME, $ EDIT, $ FLOAT, $ TEXTPROC, $ GRAPHICS.
Le sous-dictionnaire $ PRIME contenant l'ensemble de base des mots DSPP, après démarrage du processeur, est ouvert à la fois pour l'accès aux mots qu'il contient et pour le réapprovisionnement avec de nouveaux mots. Les nouveaux mots qui y sont entrés, si nécessaire, peuvent être supprimés avec les corps qui leur sont associés avec la commande FORGET $ PRIME. Après cela, la possibilité de saisir davantage de mots dans ce sous-dictionnaire est fournie en exécutant la commande GROW $ PRIME, qui permet d'augmenter à nouveau le sous-dictionnaire $ PRIME, et tout ce qui y est entré peut à nouveau être supprimé par le FORGET $ commande PRIME, etc. Dans ce mode, le PRIME est utilisé lors de l'expérimentation de petits fragments de programmes, d'exemples individuels, d'estimations et également, si nécessaire, d'inclure de nouveaux mots dans le sous-dictionnaire $ PRIME dans l'ordre du développement du langage système.
Dans le cas de la création d'un programme séparé, ils forment leur propre dictionnaire pour celui-ci, et ceci est réalisé par le fait que le texte du programme commence par la commande
PROGRAMME $<имя программы>
Une personne perçoit cette commande comme un en-tête, suivi d'un commentaire entre crochets, caractérisant en quelques mots la fonction mise en œuvre par le programme. Pour le processeur, cela équivaut à une séquence de commandes
OUBLIER $<имя>CROISSANCE $<имя>
Par conséquent, chaque réception du texte du programme à l'entrée du processeur entraînera la suppression de sa version précédente et ouvrira le sous-dictionnaire ainsi nettoyé pour la saisie nouvelle version programme portant le même nom. Ceci est pratique pour apporter des corrections au programme créé, ainsi que pour le modifier à l'avenir.
Le texte du programme construit n'est pas entré directement du clavier dans l'entrée du processeur, mais est formé dans la mémoire tampon de l'éditeur de texte. La commande E (Editer) définit le mode d'édition, dans lequel les mots tapés au clavier ne sont plus perçus par le processeur comme des commandes à exécuter immédiatement, mais sont simplement du texte écrit dans le tampon et affiché simultanément à l'écran. À l'aide de touches spéciales qui contrôlent le mouvement de l'indicateur de position actuelle (curseur) sur l'écran, ainsi que des commandes d'édition données en appuyant sur d'autres touches, le texte saisi peut être corrigé et modifié, en effectuant des suppressions et des insertions, en transférant ses fragments d'un endroit à l'autre, etc.
A la fin de la saisie et de l'édition de texte, l'éditeur s'éteint en appuyant simultanément sur la touche E (ou plutôt avec la touche précédemment enfoncée).
Lorsque le téléchargement est terminé, les procédures et les données sont disponibles pour référence par leurs noms, tapés au clavier, et vous pouvez vérifier l'exactitude du programme en exécutant les procédures dans l'ordre croissant, c'est-à-dire à commencer par ceux dont les définitions ne contiennent pas de procédures non vérifiées. Avant de commencer la vérification, il est pertinent de s'assurer qu'aucun nom non défini n'est utilisé dans le programme. Le processeur les affiche à l'écran par la commande UNDEF. Pour reconstituer le texte du programme avec les définitions de ces noms, ainsi que pour corriger d'autres erreurs détectées pendant le processus de vérification, utilisez la commande E pour appeler l'éditeur et apporter la modification appropriée du code source du programme dans le tampon de l'éditeur, puis basculez le processeur en mode principal et charge le contenu du tampon avec la commande PF.
Après vérification et test du programme, son code source peut être copié du tampon de l'éditeur sur le disque à l'aide de la commande OE f, où f est le nom du fichier sous la forme duquel le programme sera écrit sur le disque. À l'avenir, le contenu du fichier peut être chargé dans l'entrée du processeur avec la commande LOAD f, et également copié dans le tampon de l'éditeur en plus du texte qu'il contient avec la commande IE f. Par défaut, les fichiers ont l'extension .dsp. Le tampon peut être préalablement effacé avec la commande KE. Il est également possible d'imprimer le contenu du buffer avec la commande LPE.
Après avoir chargé le programme, prêt à être exécuté, il est possible de nettoyer le dictionnaire créé $<имя>avec la commande EFFACER $<имя>... En exécutant cette commande, le processeur supprime les noms non validés du sous-dictionnaire nommé, c'est-à-dire tous les noms sauf ceux avec un préfixe préfixe :: (deux points) devant leurs définitions. Dans ce cas, seuls les noms eux-mêmes (entrées du dictionnaire) sont supprimés, et les corps de procédures et les données qui leur sont associées sont sauvegardés et disponibles lors de l'exécution du programme grâce aux liens internes établis lors de la compilation, mais ils ne sont plus disponibles de l'extérieur. Pour restaurer la possibilité d'accéder de l'extérieur, par exemple, si vous devez compiler un ajout ou une modification, vous devez recharger le code source du programme.
Les noms peuvent être rendus inaccessibles de l'extérieur sans les supprimer du dictionnaire en utilisant la commande SHUT $<имя>, fermant l'accès à tous les mots du sous-dictionnaire nommé. L'ouverture du dictionnaire pour l'utilisation de ses mots s'effectue par la commande USE $<имя>... Il y a aussi SEULEMENT la commande $<имя>, qui ferme tous les sous-dictionnaires sauf celui nommé, et la commande CANCEL, qui annule cette restriction. Les commandes répertoriées vous permettent de contrôler l'utilisation du dictionnaire lors de la compilation et de restreindre l'ensemble des noms disponibles pour l'utilisateur du programme au minimum requis.
La recherche d'un nom dans le dictionnaire se fait en regardant ses mots dans l'ordre inverse de celui dans lequel ils ont été saisis dans le dictionnaire, c'est-à-dire en commençant par le dernier entré. Par conséquent, pour un nom défini plusieurs fois dans le dictionnaire, la dernière définition est valide. Si le sous-dictionnaire contenant cette dernière définition est fermé, alors la recherche se poursuit jusqu'à la première entrée de dictionnaire disponible avec le nom donné et la définition indiquée par cette entrée sera utilisée.
Quelques mots sur l'entrée et la sortie des données. Comme déjà mentionné, le processeur essaie d'interpréter le mot du programme exécutable non trouvé dans le dictionnaire comme un nombre et, en cas de succès, pousse l'équivalent binaire de ce nombre sur la pile. La saisie d'un nombre dans la pile peut être effectuée par la commande TIN, qui nécessite de taper le nombre saisi au clavier. Il existe également des commandes pour pousser un caractère entré au clavier sur la pile : TIB - avec affichage, TRB - sans afficher ce caractère à l'écran. Dans ce cas, le code lettre est représenté par l'octet de poids faible du mot de 32 bits poussé sur la pile, dont les 3 octets de poids fort sont égaux à zéro.
Le contenu du haut de la pile peut être saisi sous forme de nombre et de lettre, respectivement. La commande TON provoque l'affichage de la valeur numérique de la sous-ligne dans le champ de sortie, dont la largeur est fixée par le sommet, dans le système de représentation numérique défini lors de son exécution. La commande TOB imprime à l'écran un caractère dont le code est contenu dans l'octet de poids faible du haut de la pile. Dans les deux cas, la sortie s'accompagne de la suppression des arguments de la pile.
Le processeur DSPP dispose d'un appareil pour les interruptions externes et internes (de commande) et fournit les moyens suivants pour les traiter. La procédure de traitement d'une interruption externe est définie de manière similaire à une procédure normale, mais avec le préfixe INT ajouté avant les deux points. Le nom d'une telle procédure est associé à l'adresse du vecteur d'interruption avec la commande :
<адрес вектора>LIEN<имя процедуры>
Une interruption de commande est une opération nommée appelant une procédure de réponse. Le nom de cette opération est déterminé par la commande TRAP, qui l'associe à une procédure dite de réponse finale, effectuée dans le cas où la réponse finale n'est pas remplacée par la commande ON ou EON par une autre procédure de réponse. Les trois commandes ont le même format :
PIÈGE<имя вызова> <процедура реагирования>
AU<имя вызова> <процедура реагирования>
EON<имя вызова> <процедура реагирования>
La procédure associée au nom de l'appel par la commande EON est exécutée avec une sortie préliminaire du corps de la procédure contenant la commande EON et avec la valeur du pointeur de pile d'opérande qui s'est produit lors de l'exécution d'EON.
PARADISE syntaxe
L'alphabet de la langue PARADISE comprend le latin et le russe, des lettres majuscules et minuscules, des chiffres décimaux, des mathématiques et d'autres caractères spéciaux. Les éléments (membres) de l'alphabet sont appelés lettres. La représentation externe d'une lettre est son image imprimée (signe imprimé). A l'intérieur du processeur PRSP, chaque caractère imprimé est représenté par un octet dont la valeur est le code binaire de ce caractère. La transformation de la représentation externe en représentation interne et inversement est réalisée par le périphérique d'entrée/sortie (clavier, écran, imprimante). Pour le confort valeur numérique les codes sont exprimés en système décimal, hexadécimal ou octal, en nommant le nombre correspondant dans le code de caractère décimal, hexadécimal ou octal.
Tous les objets du langage de PARADISE sont construits à partir de lettres et représentent des chaînes linéaires de lettres de longueur finie, appelées mots. Le séparateur de mots qui se suivent est un caractère non imprimable (espace). Une chaîne d'espaces est identique à un espace. De plus, la fonction du séparateur de mots est assurée par la commande "Aller au début de la ligne suivante", désignée sur les claviers des périphériques d'entrée par le symbole
Exemples de mots : CLEAR NOP STEK2 & 1+ -366 X Sample.
Le processeur DSPP distingue les mots par les sept premières lettres, les identifiant par comparaison polymérique avec les mots de son dictionnaire. Le dictionnaire contient des mots qui sont les noms (désignations) des opérations propres du processeur, appelées opérations de base ou primitives, et peuvent être complétés par les noms d'objets définis par l'utilisateur (données, procédures). Ainsi, les mots contenus dans le dictionnaire sont soit des noms d'actions (opérations, procédures), soit des noms de données (constantes, variables, tableaux).
Lorsqu'il n'y a pas de mot reconnaissable dans le dictionnaire, le processeur essaie de l'attribuer à l'un des cas suivants :
littéral numérique, c'est-à-dire une suite de nombres, commençant éventuellement par un signe moins, par exemple : 0, 4096, -25 ;
caractère littéral : un mot commençant par le caractère #, ce qui fait que le processeur reçoit le caractère immédiatement suivant comme code donné, par exemple : #A - lettre latine majuscule A littéral, # 5 - chiffre 5 littéral, # - espace littéral, ## - lettres littérales # ;
littéral de texte : texte arbitraire entouré de guillemets doubles et séparé par des délimiteurs de mots, par exemple : "Texte", "Fichier d'entrée N3" ;
commande pour envoyer un message texte à l'affichage : le texte du message affiché, délimité à gauche par le point-guillemet double et les guillemets doubles à droite, et séparé par des délimiteurs de mots, par exemple : "La pile est vide ";
commentaire : texte arbitraire entre crochets et séparé par des séparateurs, par exemple :.
Les littéraux et la commande d'émission d'un message à l'écran agissent comme des objets du langage DSPP avec les mots reconnus par le dictionnaire, tandis que les commentaires sont complètement ignorés par le processeur DSPP - ils sont destinés à une personne, pas à une machine. Si le mot n'est pas trouvé dans le dictionnaire et n'est pas lié aux constructions listées, le processeur émet un message : "Je ne sais pas<неопознанное слово>".
En raison de la signification particulière donnée aux lettres #, "et la combinaison." au début d'un mot, c'est-à-dire après le séparateur, ainsi que la lettre "avant le séparateur, ils ne doivent pas être utilisés dans les positions indiquées dans les mots déterminés pour l'inclusion dans le dictionnaire.
Une séquence de mots en entrée du processeur est interprétée comme une séquence d'instructions exécutées par le processeur. Dans ce cas, on distingue trois sortes de mots :
1) réalisée indépendamment, c'est-à-dire qui sont des commandes d'un mot (monologues) ;
2) exécuté en conjonction avec un ou plusieurs mots suivants, c'est-à-dire qui sont les mots initiaux (préfixes) des commandes à deux, trois ou verbeuses ;
3) précédant la commande à titre de clarification ou d'indication d'un mode d'exécution particulier (pré-préfixes).
Les monologues incluent les littéraux, les noms de données, la plupart des E/S, les tests et la conversion des données sur la pile et les routines définies par l'utilisateur. Par exemple : 1987 - littéral numérique, # 5 - chiffre 5 littéral, Schema List - texte littéral, LENGTH - nom de la variable, TOB, NEG, +, &,<, = - имена (обозначения) операций, SORT, CONVERT, ЧИСТКА, СНЯТЬ - имена процедур пользователя.
Les préfixes sont inhérents aux commandes de description de données et de définition de procédures, ainsi qu'à la manipulation de données nommées, à l'exécution conditionnelle et répétée de procédures et à la gestion des dictionnaires. Exemples de commandes avec préfixes :
VAR SUM - crée une variable SUM,
: IMPAIR [x] 1 &; - créer une procédure ODD remplaçant un nombre impair par 1, pair par 0,
0 X - affecter la valeur 0 à la variable X,
BR + P1 P2 - si la valeur de son sommet prise dans la pile est positive, alors exécutez P1, sinon exécutez P2,
RP CHECK - effectuez la procédure CHECK encore et encore,
USE $ REAL - ouvre le sous-dictionnaire $ REAL à utiliser.
En règle générale, un préfixe spécifique nécessite un nombre spécifique de mots après lui. Ainsi, dans les exemples qui viennent d'être donnés, les préfixes VAR,!0 et USE nécessitent un mot chacun, et le préfixe BR + nécessite deux mots. Cependant, le préfixe : (deux points) vous permet de former une commande de longueur arbitraire, commençant par trois mots. La fin de la commande est le mot ; (point virgule). La longueur arbitraire est également inhérente à la commande - descripteur constant CNST A1 ... AJ; et la procédure de commande à choix multiples BR A1 P1 ... AJ PJ ELSE PN.
Les préfixes sont des mots spéciaux qui, ajoutés au début d'une commande, modifient son contenu ou définissent un mode d'exécution particulier. Par exemple, la commande VAR X sans préfixe est une instruction pour créer une variable X de 16 bits. Si vous lui attachez le préfixe BYTE, nous obtenons la commande BYTE VAR X, qui demande de créer une variable de 8 bits (octet) nommé X. Si vous utilisez le préfixe LONG, alors nous obtenons LONG VAR X - une instruction pour créer une variable 32 bits nommée X.
Un pré-préfixe d'un autre type, à savoir :: (deux points), rend le résultat de la commande résistant à la procédure CLEAR, qui supprime les mots non fixés du dictionnaire. Les noms entrés dans le dictionnaire dans le processus de construction d'un programme par des commandes pour décrire des données et définir des procédures, après que le programme a été créé et testé, peuvent être supprimés du dictionnaire, à l'exception de quelques-uns qui sont nécessaires pour maintenir le programme terminé. La suppression est effectuée avec la commande CLEAR $<имя подсловаря>, en demandant d'effacer le dictionnaire associé au programme, en n'y gardant que les mots dont les définitions contiennent le pré-préfixe ::. Exemples de commandes générant des mots inamovibles :
:: BYTE CNST LITCODE # # 0 #A;
::: MOD / [int (a, b), repos (a, b)] E2 D [silence (a, b)] ;
Comme le montre le deuxième exemple, qui contient les préfixes :: et BYTE, il peut y avoir plusieurs préfixes dans une commande.
Ainsi, une commande dans le DSPP peut être soit un seul mot (monologue), soit une phrase (phrase) qui commence par un préfixe et contient le nombre de mots définis pour un préfixe donné, et si le préfixe autorise un nombre arbitraire de mots , puis il a un mot délimiteur à la fin, ou il peut s'agir d'une phrase avec des pré-préfixes spéciaux devant elle.
Le langage de base du DSPN ne contient pas de constructions syntaxiques plus complexes que la commande et ne contient pas d'autres constructions que celles évoquées ci-dessus. Même des choses aussi indispensables dans les langages de programmation qu'une expression et une fonction sont absentes dans le langage de base et ne peuvent être introduites, si nécessaire, qu'au cours de son développement.
Un programme dans un langage de base est simplement un ensemble de commandes exécutées dans l'ordre dans lequel elles apparaissent dans le texte. De plus, chaque commande, à l'exception de celles ne contenant que des primitives, en cours d'exécution implique une séquence de commandes qui définissent les mots qu'elle contient. Les commandes impliquées peuvent à leur tour contenir des mots désignant des chaînes de commandes, dans lesquelles des mots sont également possibles se référant à leurs chaînes associées, etc. au niveau auquel les commandes ne contiennent que des primitives.
La description générale du langage PARADISE, qui constituait le contenu de ce chapitre, a été consacrée aux caractéristiques de la structure de ce langage et de l'ensemble de base (initial) de ses commandes, qui est un ensemble de commandes intégrées (primitives) du processeur DSPP. Le développement ultérieur du langage et l'augmentation correspondante des capacités du processeur sont réalisés en introduisant de nouvelles procédures, commandes, formats et types de données, construits à l'aide d'outils de base. En règle générale, un tel développement est orienté problème et s'effectue sous la forme de packages de procédures chargés à l'entrée du processeur en plus du système de base.
D'autre part, le système de base peut être complété par des outils spéciaux pour augmenter l'efficacité de la machine des programmes DSP mis en œuvre sur sa base. Ces outils incluent la possibilité de définir des procédures individuelles directement dans le code d'instructions de la machine utilisée. La façon dont une procédure est définie n'a aucun effet sur son utilisation ultérieure : les noms de toutes les procédures sont entrés dans un dictionnaire commun et sont complètement égaux. Un certain nombre de programmes de bibliothèque vous permettent d'utiliser des procédures ou des programmes entiers écrits dans d'autres langages.
Description des opérations et des commandes
Opérations de pile
La pile d'opérandes est l'un des principaux éléments de l'architecture du processeur DSP. La plupart des instructions du processeur utilisent la pile, en consommant les opérandes dont elles ont besoin et en y poussant les résultats. L'interprétation des données de la pile dépend de l'essence du problème à résoudre, c'est-à-dire qu'elle est finalement confiée au programmeur. Du fait que la valeur entrée dans la pile perd effectivement son nom, il est difficile de déterminer à partir du texte du programme à quels opérandes telle ou telle opération s'applique, quels en sont les résultats. Par conséquent, pour une indication explicite des opérandes et des résultats des procédures dans le langage PARADISE, des commentaires sont utilisés. Dans ce cas, il n'est pas obligatoire (et pas toujours possible) de décrire l'intégralité du contenu de la pile. Il faut absolument commenter la partie supérieure de la pile, qui est affectée par la procédure qui y est effectuée, car sans cela la visibilité du programme est perdue et sa vérification devient difficile.
Pour assurer la cohérence du programme, ces commentaires doivent être rédigés avec quelques règles simples. Comme tout commentaire, la description des données sur la pile est mise entre crochets. Cette description est une liste des opérandes qui se trouvent sur la pile à un moment donné du programme. Chaque élément de la liste caractérise le contenu d'une position de pile, une virgule est utilisée comme séparateur. Les positions de la pile sont répertoriées de gauche à droite, en commençant par l'élément le plus profond et en se terminant en haut de la pile. La description d'un opérande individuel peut être un nombre, un nom, une expression ou tout autre enregistrement significatif qui explique la signification de la valeur sur la pile. Parfois, vous pouvez spécifier plusieurs valeurs possibles pour une position de pile donnée. Dans ce cas, les valeurs sont répertoriées avec une barre oblique.
Voici un exemple de commentaire reflétant l'état de la pile d'opérandes :
[adresse de départ, N + 1,1 / 0]
Au point du programme où se trouve ce commentaire, la pile d'opérandes doit contenir au moins trois positions, et en haut il peut y avoir 1 ou 0, dans la sous-section - une valeur numérique égale à N + 1, et en dessous it - un certain nombre interprété comme l'adresse de départ.
Pour la commodité de spécifier la position requise de la pile, nous utiliserons le concept de profondeur. Nous supposerons que le sommet de l'empilement se trouve à la profondeur 1, la sous-couche est à la profondeur 2, et ainsi de suite. En particulier, la valeur indiquée dans l'exemple comme « démarrer l'annonce ». se trouve à une profondeur de 3.
Nous commencerons notre étude du langage DSPC de base par les commandes pour pousser des valeurs sur la pile. La commande la plus simple (et la plus fréquemment utilisée) de ce type est un littéral numérique, c'est-à-dire une indication explicite d'une constante à pousser sur la pile. Par exemple, supposons que nous voulions mettre sur la pile les nombres 28, -5 et 11. Pour ce faire, entrez la chaîne suivante à partir du clavier :
28 -5 11 et appuyez sur la touche
Afin d'afficher tout le contenu de la pile, le DSPP contient la commande .. (deux points). Après l'avoir exécuté, nous obtenons la ligne à l'écran :
Comme vous pouvez le voir, la forme de l'impression suit les conventions acceptées pour commenter l'état de la pile (sauf qu'un espace est utilisé au lieu d'une virgule). La commande .. ne modifie pas le contenu de la pile.
Un mot de 32 bits (4 octets) est utilisé pour représenter une position de pile dans la mémoire de la machine, les nombres sont représentés en code complément à deux. En conséquence, le processeur PRSP ne peut percevoir correctement que les entiers compris entre -2147483648 et 2147483647. Si le nombre entré n'est pas représentable par 32 bits (avec le signe), alors les bits les plus significatifs qui ne correspondent pas sont rejetés.
Dans les exemples considérés, il a été supposé que le processeur PRSP est en mode d'entrée/sortie décimal des nombres. Pour régler ce mode dans le langage PARADISE il existe une commande B10.
Dans de nombreuses tâches, il est nécessaire d'interpréter les données traitées non pas comme des nombres, mais comme des codes binaires, c'est-à-dire des vecteurs binaires à 32 composants. Dans DSPP, il est possible de travailler avec des codes présentés dans un système de nombres binaire, octal ou hexadécimal. Pour définir le mode souhaité, il suffit d'exécuter l'une des trois commandes: B2, B8 ou B16, après quoi le processeur percevra et imprimera tous les codes entrés dans le système de numérotation spécifié.
Cette fonctionnalité peut être utilisée pour convertir des nombres décimaux en base 2, 8 et 16. Par exemple, pour convertir le nombre 29, vous devez saisir et exécuter la ligne suivante :
B10 29 B2. B8. B16. En conséquence, le processeur affichera une série de nombres : 0000000035 0000001D qui sont des représentations du nombre décimal 29 dans les trois systèmes de nombres spécifiés. Notez que les codes sont imprimés dans leur représentation machine, c'est-à-dire avec des zéros non significatifs et sans signes "+", "-". Lors de l'exécution de la ligne B10 -2 B8. le nombre 37777777776 sera renvoyé, qui est la représentation octale du complément à deux de -2.
Lorsque vous travaillez avec des codes hexadécimaux, des collisions peuvent se produire entre les littéraux numériques et les noms des commandes du processeur DSPP. Par exemple, le mot B8 en mode E/S hexadécimal peut être interprété comme une commande pour définir le mode octal et comme une constante hexadécimale. Pour éviter toute ambiguïté, commencez les littéraux numériques par un zéro non significatif, tel que 0B8.
La base du système d'instructions du processeur DSPP est constituée des opérations de conversion des données de la pile. La règle générale régissant le fonctionnement de ces opérations est que chaque opération consomme (supprime) les opérandes dont elle a besoin de la pile et pousse les valeurs de résultat (le cas échéant) à leur place.
Considérez les instructions du processeur qui implémentent quatre opérations arithmétiques : addition, soustraction, multiplication et division d'entiers. Pour les décrire dans la langue de PARADISE, les mots sont utilisés : +, -, * et /, respectivement. Pour obtenir la somme de deux nombres sur la pile, par exemple 123 et 45, vous devez pousser ces nombres sur la pile et exécuter la commande +. Pour ce faire, il suffit de saisir la ligne suivante depuis le clavier (on suppose que le mode E/S décimal est défini) :
123 45 +
Si on affiche maintenant le contenu de la pile (à l'aide de la commande ..), le résultat de l'ajout deviendra visible :
L'opération de multiplication commutative fonctionne de manière similaire.
Lors de l'exécution d'opérations de soustraction et de division non commutatives, la sous-pile est considérée comme la soustraction (dividende) et le sommet est la soustraction (diviseur). Par exemple, pour calculer la différence 151-68, vous devez exécuter la ligne :
151 68 -
Un programme pour effectuer une opération arithmétique dans le langage PARADISE est caractérisé par le fait que l'opération est située après les opérandes correspondants. Cette notation d'expressions arithmétiques est appelée notation postfixe (ou notation inverse polonaise) et est largement utilisée dans les microcalculateurs à pile. Supposons, par exemple, que nous ayons besoin de calculer la valeur de l'expression arithmétique ((127 + 81) * 15- (31 + 117) * 21) * 3
En notation postfixe, cette expression ressemblera à ceci :
127 81 + 15 * 31 117 + 21 * - 3 *
Cette ligne (dans laquelle les mots sont séparés les uns des autres par des espaces) est un programme tout fait pour calculer notre expression par le processeur DSP.
La division / commande diffère des autres opérations arithmétiques en ce que son résultat est deux valeurs - quotient et reste. Le quotient est au bas de la pile et le reste est au sommet. Le quotient est négatif si le dividende et le diviseur sont de signes différents. Le reste a toujours le signe du dividende. Voici quelques exemples d'utilisation de la commande division.
125 7 / [-17,-6] / / /
Lors de la réalisation des calculs, des situations erronées peuvent survenir : débordement et division par zéro. Le processeur DSPP n'y réagit en aucune manière (en particulier, lors d'une division par zéro, le contenu de la pile ne change pas), et le contrôle de l'exactitude de l'utilisation des opérations est confié au programmeur.
Lors de la programmation, il est souvent nécessaire d'augmenter ou de diminuer la valeur d'une valeur de 1 ou 2. Des commandes spéciales ont été introduites dans le langage PARADISE qui effectuent les actions indiquées en haut de la pile. Ils sont indiqués par les mots : 1+, 1-, 2+, 2-. L'exécution de ces commandes équivaut à pousser la constante requise (1 ou 2) sur la pile, puis à effectuer l'opération arithmétique requise (+ ou -). Par exemple, 2+ équivaut à la paire de mots 2 +. L'introduction au langage de ces commandes est pour des raisons d'efficacité.
De plus, pour augmenter l'efficacité du langage de base du processeur DSP, il existe des commandes T0 et T1 qui remplacent la valeur du sommet de la pile par 0 et 1, respectivement, quelle que soit la valeur au sommet avant la commande spécifiée. Exemples:
Les commandes NEG, ABS et SGN sont également disponibles pour travailler avec des données numériques. La commande NEG inverse le signe du haut de la pile, ABS remplace la valeur du haut de la pile par son module, SGN - consomme une valeur numérique du haut de la pile et remplace le signe du nombre extrait à sa place : -1 - si le nombre est négatif, 1 - si positif, 0 - si égal à zéro. Par exemple:
5 NEG [-5] ABS SGN
Les commandes MIN et MAX du langage de base permettent de trouver le minimum et le maximum de deux entiers. Les opérandes de ces instructions sont deux nombres en haut et en bas de la pile. L'instruction MIN laisse le plus petit du nombre de paramètres sur la pile, MAX le maximum. Par exemple:
5 0 15 MIN [-5,0] MAX
Pour trouver le minimum (maximum) des trois nombres sur la pile, utilisez simplement la commande MIN (MAX) deux fois :
MIN MIN [-2]
La commande SEG pour vérifier si le nombre contenu en haut de la pile se situe dans la plage spécifiée de a à b (y compris les limites) laisse un signe sur la pile en conséquence : 1 si le nombre est dans la plage, et 0 si ne pas:
SEG [fonctionnalité] par exemple :
En plus des instructions pour travailler avec des données numériques, le jeu d'instructions pour le processeur DSPP comprend un certain nombre d'opérations conçues pour convertir des codes 32 bits. Ces opérations traitent l'élément de pile comme un vecteur de bits à 32 composants, dont les composants sont numérotés de droite à gauche de telle sorte que le bit le plus à gauche est le numéro 31 et le plus à droite est 0. La numérotation décroissante du composant répète la numérotation des bits de mots machine acceptés pour de nombreux microprocesseurs.
Les commandes exécutées sur les vecteurs de bits incluent principalement les opérations au niveau du bit de l'algèbre booléenne :
inversion au niveau du bit du sommet de la pile INV, en changeant la valeur de chaque bit du sommet, c'est-à-dire en remplaçant 0 par 1 et 1 par 0 ;
la conjonction au niveau du bit du haut et du bas de la pile &, définissant le ième bit du résultat, i = 31,30, ..., 0, à 1 si les ième bits des deux opérandes sont égaux à 1 , et dans d'autres cas définir le ième bit égal à 0 ;
une disjonction au niveau du bit du haut et du bas de la pile & 0, définissant dans le i-ème bit du résultat, i = 31,30, ..., 0, la valeur 0, si les i-ème bits des deux opérandes sont égaux à 0, et dans d'autres cas mettant le ième bit égal à 1 ;
addition au niveau du bit (non-équivalence) "+" des nœuds et sous-nœuds, qui définit le i-ème bit du résultat à 0 si les i-ème bits des deux opérandes ont les mêmes valeurs, et définit le i-ème bit du résultat à 1 si les valeurs des i-ièmes bits des opérandes sont différentes.
525 INV 722 & 136 & 0 325 "+"
La conjonction au niveau des bits est souvent utilisée pour mettre à zéro (effacer) les bits de mots. Pour ce faire, associez le mot d'origine à un masque contenant des zéros dans les chiffres à effacer et des uns dans les chiffres restants. Par exemple, si vous devez mettre à zéro les bits de 3 à 5 dans un mot X, vous devez effectuer sa conjonction au niveau du bit avec le masque 37777777707. Pour X = 235, nous obtenons :
La disjonction au niveau des bits peut être utilisée pour insérer le modèle de bits souhaité dans un groupe de mots pré-autorisé. Par exemple, supposons que vous vouliez mettre la combinaison binaire 010 dans les bits 3 à 5 du mot restant sur la pile à la suite du dernier exemple. Vous pouvez le faire comme ceci :
Les opérations de manipulation de bits incluent également des commandes de décalage logique :
décalage à gauche SHL - chaque bit du haut de la pile, à partir du 31, prend la valeur du suivant dans l'ordre décroissant des nombres, et le dernier bit zéro prend la valeur 0;
décalage à droite SHR - chaque bit du haut de la pile, à partir de 0, prend la valeur du suivant dans l'ordre croissant des nombres, et le 31e bit prend la valeur 0 ;
décalage le long du haut SHT - l'élément du haut est extrait de la pile et traité comme un entier N, indiquant combien de décalages et dans quelle direction doivent être effectués en haut de la pile : lorsque N> 0, un décalage est effectué vers le à gauche, quand N<0 - вправо.
B8 125 SHR SHL -2 SHT
Les opérations de décalage à gauche peuvent être utilisées pour multiplier les nombres par 2 à la puissance N, où N est un nombre naturel qui détermine le nombre de décalages. Par exemple, multiplier le nombre -5 par 8 peut se faire en décalant ce nombre de 3 chiffres vers la gauche :
B10 -5 3 SHT [-40]
Dans ce cas, la possibilité de débordement doit être prise en compte.
Le décalage vers la droite peut être utilisé comme une opération de division entièrement par 2 à la puissance N uniquement pour les nombres positifs, puisque le bit le plus significatif (signe) est mis à zéro lors du décalage vers la droite. Par exemple:
tandis que
Les commandes pour faire pivoter le haut de la pile de 1 bit vers la droite ROR et la gauche ROL sont similaires aux commandes de décalage logique, sauf que le bit extrême étendu ne disparaît pas, mais est poussé dans l'espace vacant depuis l'extrémité opposée d'un 32 -un mot long. Par exemple (nombres hexadécimaux) :
Pour le traitement des codes binaires, les commandes du processeur DSPP SWB et SWW sont également destinées. La fonction SWB consiste à échanger les octets de la moitié inférieure du sommet de la pile et la fonction SWW consiste à échanger les moitiés du sommet de la pile. Illustrons le fonctionnement de ces commandes en utilisant le mode E/S hexadécimal (dans ce mode, chaque octet est représenté par deux chiffres hexadécimaux) :
B16 0ABCD SWB SWB
0ABCDEF12 SWW SWB
Les instructions de manipulation de pile jouent un rôle important dans le langage PARADISE. Ils ne modifient pas les valeurs des données sur la pile, mais modifient uniquement leur emplacement, ce qui facilite l'accès aux opérandes situés au plus profond de la pile.
Il existe trois commandes pour supprimer des membres de la pile : D, DD, DS (Drop). La commande D supprime un élément (supérieur) de la pile, DD - deux éléments, par exemple :
D DD D DS supprime tous les éléments de la pile (efface la pile) :
La commande de copie du sommet de la pile C (Copier - copier) pousse sur la pile une copie de la valeur courante de son sommet. Cela revient à dupliquer l'élément supérieur de la pile : l'ancien sommet devient le sous-ensemble, et sa copie devient le nouveau sommet. Exemple:
Montrons l'application de cette commande par l'exemple du calcul du polynôme p (x) = 3 * x ** 2 + 4 * x-5 selon le schéma de Horner : p (x) = (3 * x + 4) * x -5. On suppose que x est au sommet de la pile.
[x] C 3 * 4 + * 5 -
A côté de la commande de copie du haut de la pile dans le langage PARADISE, il existe également les commandes C2, C3, C4, qui recopient des éléments situés aux profondeurs 2, 3, 4. Leur travail peut être illustré par les exemples suivants :
C2 C4
Il existe également une commande CT pour copier l'élément à la profondeur indiquée en haut de la pile. En exécutant CT, le processeur extrait l'élément supérieur de la pile, utilise sa valeur comme indicateur de la profondeur de l'élément copié et pousse une copie de ce dernier sur la pile. Ainsi, la copie d'un élément situé à une profondeur de 5 est définie par une paire de 5 commandes CT, une fois exécutée, le processeur poussera le numéro 5 sur la pile, puis exécutera la commande CT. L'exécution de CT avec les paramètres 1, 2, 3, 4 équivaut respectivement à C, C2, C3, C4.
Les commandes d'échange E2, E3, E4 (Echange - échange) effectuent la permutation du premier élément (supérieur) de la pile, respectivement, avec le 2e, 3e, 4e, c'est-à-dire avec l'élément situé à une profondeur de 2, 3 , 4. Par exemple:
E3 E2
Pour échanger pour une plus grande profondeur, on utilise la commande ET, qui, comme CT, utilise la valeur du haut de la pile comme indicateur de la profondeur de l'élément, qui est échangé avec le premier élément. Par exemple:
5 HE
La commande ET avec les paramètres 2, 3, 4 est équivalente aux commandes E2, E3, E4.
Pour illustrer l'utilisation des commandes de copie et de partage, considérons un problème de didacticiel. La pile contient trois nombres. Il est nécessaire pour monter sur la pile :. Le programme suivant peut être proposé, dont le sens ressort clairement des commentaires.
C3 C3 C3 +
E4 + E4
Cet exemple montre bien à quel point le rôle des commentaires, reflétant l'état de la pile d'opérandes, est important.
Les programmes doivent souvent comparer des valeurs numériques entre elles et effectuer diverses procédures en fonction des résultats de la comparaison. Il existe des commandes de comparaison dans le langage PARADISE<, =, >... Ils sont définis sur des nombres et renvoient comme résultat les valeurs numériques 0 et 1. Par exemple, la commande< потребляет из стека два элемента и засылает в стек число 1, если значение нижнего элемента оказалось меньше значения верхнего, а в противном случае засылает 0. Например, в результате выполнения последовательности 5 -20 < в стек будет заслан 0. Команда = засылает 1 в случае равенства потребленных ею элементов. Команда >envoie 1 lorsque l'élément du bas est plus grand que le haut. Pour programmer des comparaisons non strictes (inférieur ou égal, supérieur ou égal), utilisez la commande NOT, qui remplace une valeur non nulle sur la pile par zéro, mais zéro par un. Par exemple, l'évaluation de l'expression logique x> = 5, où x est un nombre situé en haut de la pile, peut être spécifiée comme suit :
[x] 5< NOT
Une extension supplémentaire des possibilités de conditions de programmation est fournie par l'utilisation, avec les commandes de comparaison, des opérations logiques de conjonction & (OU logique) et de disjonction & 0 (OU logique). Supposons, par exemple, qu'il soit nécessaire d'obtenir 1 sur la pile si le nombre x au sommet appartient au demi-segment C 5< NOT C2 10 <
& E2 2 = & 0
Les contrôles du programme en fonction des résultats de la comparaison seront discutés plus tard.
Définir des procédures
En tant que technique de programmation de base, le PRSP offre à l'utilisateur la possibilité de définir des séquences d'opérations nommées appelées procédures. Supposons, par exemple, qu'il faille calculer les valeurs du trinôme carré 3 * x ** 2-4 * x + 9 pour les valeurs données de x. Dans ce cas, vous devez définir une procédure qui implémente la formule trinôme et afficher le résultat dans le terminal, puis appliquer cette procédure à des valeurs spécifiques de x. La procédure requise, appelons-la PX, est définie comme suit : : PX [x] C 3 * 4 - * 9 +. RÉ; Un deux-points indique une opération de "définition de procédure", avec le nom de la procédure suivi de deux-points après un espace de séparation. La séquence de définition des commandes (corps de la procédure) suit le nom de la procédure et se termine par un point-virgule. En bref, la procédure est définie sous la forme :
: <имя процедуры> <тело процедуры> ;
Dans le langage PARADISE, il est demandé de commenter l'état de la pile d'opérandes au début et à la fin de la procédure. Dans le corps de la procédure, des commentaires sont placés à la discrétion du programmeur à des endroits difficiles à comprendre.
Les commentaires aident une personne à comprendre et à utiliser la procédure, tandis que le processeur ignore simplement tout ce qui est entre parenthèses. Par conséquent, si vous saisissez la définition d'une procédure individuelle depuis le terminal, vous pouvez omettre les commentaires.
Après avoir saisi la définition de la procédure et en appuyant sur la touche
* 2 PX
* 3 PX
* 4 PX
Définissons une procédure plus générale pour calculer un trinôme de la forme a2 * x ** 2 + a1 * x + a0, qui nous permet de spécifier les valeurs à la fois de x et a0, a1, a2. Appelons-le PXA :
: PXA C E4 E3 * + * +;
Lors de l'utilisation de PXA, les valeurs de a0, a1, a2, x doivent être dans l'ordre requis sur la pile. Par exemple : a0 = 1, a1 = 2, a2 = -3, x = 4
* 1 2 -3 4 PXA. ré
Dans le corps d'une procédure, en plus des opérations de base du processeur, il peut y avoir des procédures définies par l'utilisateur. Par exemple, vous pouvez définir une routine P qui, en plus des calculs PXA, écrira une copie du résultat dans le terminal et supprimera le résultat de la pile.
: P PXA. RÉ;
En particulier, le corps d'une procédure peut inclure le nom de la procédure en cours de définition, c'est-à-dire que la procédure peut être récursive. Par exemple:
: HEURE [t] 1- HEURE;
Cette procédure diminue la valeur du sommet de la pile de 1 et se réfère à nouveau à elle-même, c'est-à-dire qu'elle fonctionne comme un compteur de temps.
Le compteur de TEMPS, en principe, ne peut pas s'arrêter : la procédure de soustraction sera répétée tant que le processeur fonctionnera. Mais dans le DSPP, il existe des moyens qui vous permettent de contrôler le déroulement du processus en fonction des résultats obtenus - l'opération de contrôle du déroulement du programme.
Exécution conditionnelle et répétition
Un programme, qui est une séquence de commandes exécutées dans l'ordre de leur emplacement les unes après les autres dans son enregistrement, est dit linéaire. Pour rendre le programme facilement observable (lisible) et compréhensible, il est divisé en parties nommées qui ont une certaine signification - des procédures, chacune définie par sa propre séquence de procédures, qui à leur tour sont définies par des séquences de procédures plus petites, etc. aux procédures définies directement par des séquences de commandes DSPP. Un tel programme, écrit sous la forme d'une hiérarchie de définitions de procédures, est appelé structuré. La méthode de construction d'un programme structuré, qui consiste à décomposer progressivement le problème à résoudre en sous-tâches de plus en plus petites, est appelée programmation structurée.
La création non seulement de programmes linéaires, mais également de programmes par la méthode de programmation structurée est possible s'il existe des opérations pour exécuter la procédure par condition, répéter la procédure et quitter la procédure répétée. L'ensemble de commandes de ce type disponibles dans le DSPP offre la possibilité d'une construction structurée d'un programme arbitraire.
Les conditions d'exécution ou de non-exécution de la procédure sont formulées par rapport au signe du nombre, plus précisément par rapport au signe de la valeur que possède actuellement le sommet de la pile. La commande principale de l'exécution conditionnelle de la procédure - BRS (BRanch on Sign - pour brancher par signe) demande d'exécuter l'une des trois procédures nommées d'après BRS, selon le signe de la valeur courante du sommet de la pile. En exécutant BRS, le processeur extrait l'élément supérieur de la pile, teste sa valeur et s'il est négatif, il exécute la première des procédures nommées, si elle est égale à zéro, puis la seconde et si elle est positive, la troisième. Alors l'équipe
provoquera la suppression d'un élément de la pile et l'exécution de la procédure N si la valeur supprimée est négative, l'exécution de la procédure P si positive et l'exécution de la procédure Z si elle est nulle.
Un exemple d'utilisation de la commande BRS est définition suivante Procédures SGN
: SGN [X] BRS -1 0 1;
Cette routine remplace la valeur X en haut de la pile par -1 si X<0, числом 0, если X=0, и числом 1, если X>0. La procédure SGN est disponible dans le PRSP en tant qu'opération de base du processeur.
La commande BRS, associée au choix d'une procédure parmi trois données, offre la possibilité de mettre en œuvre des opérateurs à deux chiffres de la forme SI-ALORS et SI-ALORS-ELSE. Par exemple, l'instruction si x> 0 alors P1 sinon P0 correspond à la commande BRS P0 P0 P1, et l'instruction si x<>0 puis P - BRS P NOP P commande, où NOP est le nom d'une opération vide. Mais dans le DSPP, il existe une implémentation plus efficace des conditions à deux chiffres - les commandes IF-, IF0, IF +, BR-, BR0, BR +.
Les commandes IF correspondent à l'instruction IF-THEN. Par exemple, l'instruction IF-P demande de sortir l'élément supérieur de la pile et de tester son signe, et si cet élément a un signe moins, alors exécutez la procédure P. Les instructions IF0 P et IF + P demandent d'exécuter le P procédure, respectivement, dans le cas où l'élément sauté est égal à zéro, et dans le cas où sa valeur est positive.
A titre d'exemple illustrant l'utilisation des commandes du groupe IF, donnons la définition de la commande du langage de base ABS, qui calcule le module du haut de la pile.
: ABS [X] C IF-NEG [|X |] ;
Les commandes BR-, BR0 et BR + correspondent à l'instruction IF-THEN-ELSE, vous demandant de choisir l'une des deux procédures nommées d'après elles. Si le signe de l'élément extrait de la pile coïncide avec celui de la désignation de la commande, alors la procédure nommée en premier est exécutée, et si elle ne correspond pas, alors la deuxième procédure est exécutée. Par exemple, l'instruction BR0 P0 P1 demande d'exécuter la procédure P0 dans le cas où l'élément sorti de la pile est égal à zéro, et si cette condition n'est pas satisfaite, exécutez la procédure P1.
Les commandes envisagées permettent de programmer économiquement l'exécution de la procédure en fonction des conditions données. Les conditions les plus courantes de la forme x<0, x=0, x>0 sont directement mis en œuvre par les équipes du groupe IF. Conditions x<=0, x<>0, x> = 0 sont programmés avec les commandes BR-, BR0, BR + en utilisant une opération NOP vide comme première procédure. Par exemple, si x<=0 then P соответствует команда BR+ NOP P. Примером использования команд группы BR может служить следующая реализация команды базового языка NOT, заменяющей нулевое значение вершины стека единицей, а ненулевое - нулем.
: PAS [x] BR0 1 0;
Le branchement de programme est souvent effectué après des commandes de comparaison (<, =, >) qui produisent une valeur logique de 1 ou 0, selon le résultat de la comparaison des deux nombres. La commande de langage de base MAX, par exemple, peut être programmée comme suit :
: MAX C2 C2< IF+ E2 D ;
Le groupe de commandes de branchement comprend également la commande de sélection BR, écrite sous la forme :
BR A1 P1 A2 P2 ... AK PK ... AN PN ELSE P0
Lors de l'exécution de cette instruction, le processeur exécute d'abord la procédure A1 et compare la valeur qu'il a poussée sur la pile avec la valeur en dessous au sommet précédent de la pile. Si les valeurs correspondent, les deux premiers éléments sont supprimés de la pile et la procédure P1 affectée au pointeur A1 est exécutée, après quoi la transition vers la commande suivant la commande BR est effectuée (c'est-à-dire dans l'enregistrement ci-dessus de le programme suivant le mot P0 dans le texte). Si les valeurs comparées ne correspondent pas, alors un élément supérieur est retiré de la pile (c'est-à-dire le résultat A1) et les mêmes actions sont effectuées avec la paire A2 P2, puis, si la correspondance n'a pas fonctionné, alors avec la paire A3 P3, etc... jusqu'à AN PN inclus. Dans le cas où aucune des tentatives n'a donné de correspondance, la procédure P0 nommée d'après le mot ELSE est exécutée. Généralement, les constantes numériques agissent comme des procédures de pointeur, par exemple :
[x] C BR 5 NEG -3 ABS 0 PAS AUTRE T0 [y]
Suite à l'exécution de cette ligne en haut de la pile, la valeur y = -5 sera obtenue si x = 5 ; y = 3 si x = -3 ; y = 1 si x = 0 et y = 0 sinon.
D'une manière générale, une procédure de pointeur peut être non seulement une constante numérique, mais aussi une variable ou toute autre procédure qui satisfait une exigence simple : elle ne fait rien sortir de la pile et pousse une valeur sur la pile.
Pour illustrer l'utilisation des opérations d'exécution conditionnelles, nous modifions la procédure TIME dans la section précédente afin que le compteur s'arrête lorsque la condition est spécifiée :
: HEURE [t] 1- C SI + HEURE;
Désormais, cette routine TIME ne s'appelle que lorsque le sommet de la pile est positif. Le compteur sera déclenché exactement N fois si au début de la première exécution de TIME le sommet contient un nombre positif N. Par exemple, pour obtenir 7 déclencheurs, vous devez définir
7 TEMPS<ВК>
Étant donné que IF + dans la définition TIME, comme toute opération conditionnelle, fait sortir l'élément testé de la pile et que cet élément est requis pour les opérations suivantes, il doit être dupliqué en plaçant l'opération C (Copy) avant IF +.
La récursivité n'est pas le principal moyen d'exécuter une procédure plusieurs fois. Pour programmer des boucles dans le langage PARADISE, il existe des commandes RP (Repeat) et DO (Do - do, execute).
La commande RP W demande d'exécuter la procédure W encore et encore un nombre illimité de fois. Pour que les répétitions s'arrêtent, le corps de la procédure W doit contenir une opération EX (Sortie) à effectuer dans la condition donnée. L'opération EX passe à l'exécution de la procédure qui suit la procédure répétée contenant cette opération EX dans le texte du programme. Ainsi, le compteur implémenté ci-dessus comme procédure TIME récursive peut être programmé comme une répétition de la procédure W, qui se définit ainsi :
: W [t] 1-C IF0 EX;
Pour que le compteur fonctionne 25 fois, vous devez exécuter la ligne
Outre l'opération EX, qui est utilisée dans les commandes d'exécution conditionnelles, il existe des opérations de sortie conditionnelles EX-, EX0, EX +, qui produisent le même effet que les commandes IF-EX, IF0 EX, IF + EX, c'est-à-dire qu'elles consomme en haut un élément qui teste son signe et effectue une sortie si le signe correspond à celui indiqué dans la désignation de l'opération. Les opérations EX, EX-, EX0, EX + peuvent être utilisées non pas nécessairement dans le corps de la procédure répétitive elle-même (dans notre cas, W), mais aussi dans les procédures auxquelles elle se réfère.
A titre d'exemple, considérons le problème de trouver le plus grand diviseur commun de deux nombres naturels par la méthode d'Euclide. L'essence de la méthode est qu'il est nécessaire de soustraire le plus petit nombre du plus grand nombre jusqu'à ce que les nombres deviennent égaux les uns aux autres. Lorsque l'égalité est atteinte, le plus grand diviseur commun sera trouvé.
La programmation sera réalisée par la méthode du développement descendant. Tout d'abord, nous définissons la procédure GCD, qui fixe le schéma général de l'algorithme. Les paramètres de cette procédure sont deux nombres M et N sur la pile, pour lesquels on trouve le plus grand diviseur commun. Dans le corps de la procédure GCD, un processus cyclique de conversion des valeurs de la pile doit être spécifié. À la suite de ce processus, deux nombres égaux doivent rester sur la pile - n'importe lequel d'entre eux peut être considéré comme le plus grand diviseur commun. Compte tenu de ces considérations, la procédure GCD peut être définie comme suit.
: GCD RP STEP [nœud (M, N), nœud (M, N)] D [nœud (M, N)] ;
Il faut maintenant programmer une étape du processus itératif, c'est-à-dire définir la procédure STEP. Les paramètres pour cela sont deux nombres sur la pile. Vous devez comparer ces nombres et quitter la boucle s'ils sont égaux, sinon, soustrayez le plus petit du plus grand. Cela peut être fait, par exemple, comme ceci :
: ÉTAPE C2 C2 - BRS NOP EX E2 C2 -;
Maintenant, il n'y a plus de procédures non définies dans le programme et vous pouvez commencer à le vérifier. Le contrôle doit être effectué de bas en haut, c'est-à-dire que vous devez d'abord vous assurer que la procédure STEP fonctionne correctement et ensuite seulement - GCD.
L'opération DO du langage de base provoque la répétition de la procédure nommée d'après N fois, où N est le nombre contenu en haut de la pile au moment où DO est exécuté. Par exemple, pour que la procédure P soit exécutée 8 fois, vous devez définir
8 DO P
Si le corps de la procédure P contient au moins une opération de sortie et que la condition de son exécution est satisfaite avant que le nombre de répétitions spécifié ne se produise, alors les répétitions seront terminées en quittant la procédure, tout comme cela se fait dans le cas de la Opération RP. Par exemple, si DO répète la procédure W décrite ci-dessus et a IF0 EX dans sa définition, écrire [T] 30 DO W entraînera 30 répétitions de W si T> = 30. Si 0 Si au moment de l'exécution de l'opération DO il y a une valeur nulle ou négative en haut de la pile, alors la procédure suivant le DO ne sera pas exécutée même une fois. Pour illustrer l'utilisation de l'opération DO, nous définissons une routine NUM qui compte le nombre de bits non nuls dans le mot de 32 bits x spécifié en haut de la pile. Placez le compteur du nombre d'unités dans la sous-pile. Le comptage des uns consistera à répéter 32 fois la procédure NUMI, dans laquelle nous examinerons un bit du mot x. À la sortie de la boucle, le numéro requis doit être dans la sous-pile. : NUM [x] 0 E2 32 DO NUMI D [N]; Pour compter les bits non nuls, nous utiliserons le fait que celui du bit le plus significatif (31e) du mot sert de signe à un nombre négatif. Si le mot à l'étude est négatif, ajoutez un à N. À la fin de la procédure NUMI, vous devez décaler le mot à l'étude d'un chiffre vers la gauche. : NUMI C IF-N + SHL ; La mise en œuvre de la procédure N+ est assez simple : il faut en ajouter un à la sous-couche de la pile sans changer les sommets. : N + E2 1+ E2; Les procédures répétées peuvent contenir des opérations RP et DO dans leur corps, entraînant l'apparition de boucles imbriquées, et toute profondeur d'imbrication est autorisée. Dans ce cas, il existe une opération EXT pour sortir de la boucle imbriquée indiquant la profondeur d'imbrication au sommet de la pile. Par exemple, la sortie de deux boucles imbriquées peut être définie comme ceci : Il convient de garder à l'esprit que l'utilisation de la commande EXT nécessite des précautions supplémentaires, car lorsque le programme est modifié, la profondeur d'imbrication des boucles peut changer et la constante correspondante avant EXT devra être modifiée. La pile d'opérandes est le principal, mais pas le seul, mécanisme de manipulation de données dans le PRSP. Il est également possible, avec les définitions de procédure, de déclarer des éléments et des collections d'éléments organisées de manière standard (appelées structures) de données, qui sont ensuite disponibles pour une utilisation par leurs noms. En mettant en œuvre des déclarations de données, le processeur réserve la mémoire nécessaire à leur stockage et fournit les mécanismes nécessaires pour accéder à cette mémoire. Le langage de base du DSPN comprend un certain nombre de mots directifs décrits ci-dessous pour déclarer des variables et des tableaux. Afin d'étendre le langage du système, d'autres mots de ce type et, par conséquent, d'autres éléments et structures de données peuvent y être introduits. Le mot VAR déclare une variable numérique de 16 bits. Par exemple, l'entrée déclare une variable X, c'est-à-dire qu'il indique au processeur que le nom X est le nom d'une variable. Le processeur associe à ce nom un emplacement mémoire de 16 bits dans lequel sera stockée la valeur de cette variable. L'instruction pour affecter la variable X à la valeur qui est contenue dans le haut de la pile d'opérandes a la forme Lors de l'exécution de cette commande, le processeur extrait l'élément supérieur de la pile et écrit sa valeur à l'emplacement alloué à la variable X. Une commande constituée uniquement d'un nom de variable sans lettre ! Provoque le push de la valeur de cette variable sur la pile, et le push est effectué en copiant le contenu de l'emplacement mémoire correspondant, c'est-à-dire que la valeur de la variable reste inchangée . Ainsi, toute entrée dans le programme du nom de la variable X, à moins qu'elle ne soit immédiatement précédée d'un mot prescrivant une action différente, poussera la valeur courante de cette variable sur la pile, tout comme les nombres directement spécifiés (littéraux numériques) sont poussés sur la pile. A titre d'exemple, donnons une autre version de la procédure GCD discutée ci-dessus dans laquelle deux variables de travail sont utilisées. : DIEU! X! Y RP ÉTAPE X [GCD] ; : ÉTAPE X Y = EX + X Y BR + X-Y Y-X; : X-Y X Y -! X; : Y-X Y X -! O ; Comme vous pouvez le voir, le programme est devenu un peu plus long, mais sa clarté a augmenté. Le mot VCTR déclare un tableau unidimensionnel (vecteur) de cellules de 16 bits, et le numéro de l'élément le plus significatif de ce tableau est donné par la valeur du sommet. Par exemple, suite à l'écriture 9 VCTR ROW Le processeur réserve 10 mots de mémoire de 16 bits adressables séquentiellement, formant un vecteur ROW (0:9). Tout d'abord, le nombre 9 est poussé sur la pile, puis la procédure VCTR est exécutée, qui utilise l'élément supérieur de la pile pour déterminer la longueur du vecteur ROW à créer. Pousser la valeur du j-ième élément du vecteur ROW, 0 à la pile<=j<=9, задается командой [j] LIGNE En utilisant le numéro d'élément sur la pile comme paramètre, le nom du vecteur ROW provoque le remplacement de ce numéro par la valeur de l'élément correspondant. Si le mot ! est immédiatement avant le nom du vecteur ROW, alors la valeur du sous-chemin est affectée à l'élément de ce vecteur indiqué par le sommet, et la profondeur de la pile diminue de 2. Par exemple, vous pouvez mettre à zéro le 5e élément du vecteur ROW comme suit : Il y a aussi la possibilité de créer des vecteurs constants, c'est-à-dire vecteurs de nombres 16 bits dont les valeurs ont été déterminées lors de sa déclaration et ne seront pas modifiées à l'avenir. Ainsi, un vecteur de constantes de 16 bits VC de longueur L + 1 est déclaré à l'aide du mot CNST sous la forme : CNST VC k0 k1 ... kL ; où k0, k1, ... kL sont des commandes poussant une valeur sur la pile. Le plus souvent, ce ne sont que des littéraux numériques, mais il peut également y avoir des noms de variables, des procédures, ainsi que des commandes constituées de paires de mots, comme, par exemple, la commande pour définir l'adresse de la variable "X" discutée ci-dessous. aux composantes des vecteurs ordinaires. Par exemple : Un tableau multidimensionnel de mots de 16 bits est déclaré à l'aide du mot ARR, précédé des valeurs d'index maximum pour chaque dimension et du nombre de dimensions. Par exemple, un tableau 3D TIR (0 : 8.0 : 2.0 : 24) est déclaré comme ceci : Le nombre 3 immédiatement avant ARR indique la dimension du tableau déclaré. L'insertion d'un élément de tableau sur la pile est obtenue en spécifiant l'index de cet élément suivi du nom du tableau. Par exemple, la commande pour pousser l'élément TIR (0,2,2) sur la pile est exprimée comme En conséquence, l'affectation à cet élément de la valeur courante du sommet de la pile est fixée par la commande Tous les exemples considérés illustrent la création de structures à partir de mots de 16 bits. Cependant, le langage permet également de définir des structures de mots de 32 bits et d'octets de 8 bits. Pour ce faire, le préfixe LONG ou BYTE est placé avant le mot définissant la structure, respectivement. Par exemple, 5 BYTE VCTR X - définition d'un vecteur à 6 composants d'octets X ; OCTET CNST Y 65 66 67 ; - définition d'une constante vectorielle Y d'octets à 3 composantes ; 10 20 2 LONG ARR MTRX - définition d'une matrice de mots longs MTRX (0 : 10,0 : 20). La lecture des éléments des structures de mots et d'octets se fait de la même manière que dans le cas des structures de mots de 16 bits. Si la longueur de l'élément est inférieure à 32 bits, la valeur extraite est placée dans le mot ou l'octet le moins significatif du sommet de la pile, et la partie supérieure du sommet est mise à zéro. Le mot ou l'octet le moins significatif du mot de 32 bits de la pile est également considéré comme la valeur attribuée à un élément d'une structure de mot ou d'octet. Bien que le format de mot de 16 bits soit utilisé par défaut pour définir les données, il a également une notation WORD. Il est conseillé d'utiliser ce pré-préfixe lorsque le programme est censé être transféré sur d'autres machines, où le DSSP est également implémenté et la valeur par défaut peut être différente. Les structures de données d'octets sont le plus souvent utilisées pour stocker et traiter des informations textuelles. Cela est dû au fait qu'un octet est alloué dans la mémoire de l'ordinateur pour coder un caractère. Pour définir les codes des lettres dans le langage PARADISE, il existe une construction #l, où l est n'importe quelle lettre disponible sur le clavier de l'ordinateur. Le processeur DSPP perçoit cette construction comme une commande pour pousser la lettre l dans la pile. Par exemple: Cette construction effectue les mêmes actions qu'un littéral numérique égal au code de la lettre spécifiée, mais son utilisation est plus préférable, car, d'une part, elle vous libère de la nécessité de mémoriser des codes et, d'autre part, rend les programmes plus compréhensibles. En particulier, on peut donner la définition suivante d'un vecteur constant Y : BYTE CNST Y #A #B #C; Il est souvent pratique d'utiliser la notation symbolique d'une constante numérique dans un programme. Le mot de définition VALUE est disponible pour fournir cette capacité : Cette commande fait sortir l'élément du haut de la pile et forme le mot avec le nom qui suit immédiatement VALUE. Utiliser ce mot revient à utiliser une constante numérique. Par exemple: Les moyens considérés offrent la possibilité de nommer des données et de manipuler des données quel que soit le système d'adressage de l'ordinateur. Mais le langage de base comprend également des moyens pour manipuler les adresses des éléments mémoire. L'adresse d'une variable ou d'un élément du tableau X est poussée sur la pile par la commande Dans le cas d'un élément de tableau, cette commande est précédée de la valeur du ou des index(s). La commande du langage hôte @ remplace l'adresse d'un mot mémoire long en haut de la pile par la valeur qui contient ce mot. Par exemple, la valeur de Y peut être poussée sur la pile en exécutant la ligne suivante : @B remplace l'adresse par la valeur de l'octet correspondant, en supposant zéro octet de poids fort, et @L remplace l'adresse par un mot de 32 bits. Il existe également des commandes pour écrire des valeurs en mémoire. La commande!T écrit à l'adresse extraite du haut de la pile la sous-valeur de 16 bits. La commande !TB provoque une écriture similaire de l'octet de poids faible du sous-octet sur l'octet adressé par le dessus, et !TL écrit le mot de 32 bits du sous-sous sur le mot adressé par le dessus. Par exemple, vous pouvez affecter la valeur 15 au cinquième élément du vecteur d'octets BV (0 : 5) avec les commandes suivantes : 15 5 "BV! TB Le besoin de travailler avec de la mémoire à des adresses physiques survient généralement lors de la création de programmes qui dépendent de l'architecture d'un ordinateur particulier, par exemple lors de la création de pilotes d'entrée/sortie. Afin d'obtenir une plus grande efficacité et compacité des programmes, les opérations suivantes ont été introduites dans le langage PARADISE : 0 <имя переменной>- réinitialiser la variable ; 1 <имя переменной>- affecter une unité à une variable ; 1- <имя переменной>- diminuer la valeur de la variable de un ; 1+ <имя переменной>- augmenter de un la valeur de la variable ; !- <имя переменной>- soustraire la valeur du sommet de la pile de la variable ; !+ <имя переменной>- ajouter la valeur du haut de la pile à la variable. Chacune de ces opérations est facilement programmée à l'aide de commandes de lecture et d'écriture pour les variables. Par exemple, 0 X équivaut à 0 ! X 1+ X équivaut à X 1+ ! X X est équivalent à X E2 -! X L'utilisation de ces opérations augmentera l'efficacité et la clarté des programmes. En pratique, vous souhaitez souvent affecter une seule valeur à tous les éléments d'un tableau. Pour cela, il existe une opération dans le langage PARADISE !!!<имя массива>... Son action est d'affecter la valeur du sommet de la pile à tous les composants du tableau spécifié. Opération!!! applicable aux tableaux avec des éléments de n'importe quel format. Exemple d'utilisation : un code de caractère espace est écrit dans tous les composants du tableau d'octets BUF. Il est souvent nécessaire d'obtenir des informations dans le programme sur la structure de données derrière le nom. Une paire de commandes TAILLE ? - donner le format de la donnée : 1, 2 ou 4 octets, et DIM ? - donner le nombre de données dans la structure. Par exemple, si les données sont déclarées 3 4 2 ARR Z LONG alors appliqués à eux, ces commandes donneront le résultat suivant (nombres décimaux) : TAILLE? TAILLE X ? TAILLE Y ? Z FAIBLE? X DIM ? Y DIM ? Z L'ensemble d'instructions du processeur DSPP comprend, en plus, quatre commandes qui vous permettent de lire et d'écrire des bits individuels des cellules mémoire de l'ordinateur. Ce sont les commandes @BI,!BI,!BI0,!BI1. Les paramètres pour chacun d'eux sont l'adresse du mot mémoire situé sur la pile et le numéro de bit dans ce mot (rappelons que les bits sont numérotés de droite à gauche, en partant de zéro). La commande !BI suppose également qu'il y a un bit sur la pile et une valeur à écrire. La commande @BI remplace les paramètres spécifiés par la valeur du bit sélectionné (0 ou 1), les commandes!BI0 et!BI1 mettent respectivement le bit sélectionné à 0 et 1, en supprimant leurs paramètres de la pile, et le!BI La commande définit le bit sélectionné à la valeur du bit le moins significatif du troisième élément de la pile et supprime ses trois paramètres de la pile. Par exemple, si la valeur de la variable X est un nombre binaire 101101, les résultats des opérations répertoriées seront les suivants : "X [addr.X] 3 @BI - troisième bit de X, 0" X 3! BI - X est égal à 100101, "X [adr.X] 0! BI0 - X est égal à 100100, "X [adr.X] 1! BI1 - X est 100110. Dans le langage PARADISE, il existe également des fonctionnalités pour travailler avec des chaînes d'octets situées en mémoire. Pour définir une chaîne d'octets, deux paramètres sont placés sur la pile : l'adresse de début de la chaîne (c'est-à-dire l'adresse de son premier octet) et la longueur de la chaîne (le nombre d'octets qu'elle contient). La commande !!!MB est utilisée pour affecter tous les octets d'une chaîne à une valeur (définie sur la pile). Il consomme trois paramètres de la pile : où b est la valeur attribuée, a et l sont respectivement l'adresse de début et la longueur de la chaîne d'octets. Supposons, par exemple, que vous ayez besoin de zéro éléments du 3e au 10e tableau d'octets TXT (0:20). Pour ce faire, vous pouvez exécuter la ligne suivante : 0 3 "TXT 8 !!! Mo en conséquence, huit éléments consécutifs du tableau spécifié, à partir du 3e, recevront la valeur 0. Une commande similaire !!! MW est destinée à remplir une séquence de mots de 16 bits avec la même valeur (le nombre de mots est indiqué en haut de la pile), et la commande ! !! M - pour remplir une séquence de mots longs. La commande!SB transfère des chaînes d'octets. Ses paramètres sont : où a1 et l sont l'adresse de début et la longueur de la chaîne transférée, a2 est l'adresse de début de la chaîne vers laquelle le transfert est effectué. Suite à l'exécution de la commande !SB, une chaîne d'octets de longueur l sera localisée en mémoire à partir de l'adresse a2, qui est une copie exacte de la chaîne située à l'adresse a1 avant que le transfert ne soit effectué. La chaîne source et la chaîne de destination peuvent se chevaucher. Par exemple, supposons que vous vouliez déplacer les éléments du tableau d'octets M (0:10) comme suit : M (10) : = M (9), M (9) : = M (8), ..., M (1) : = M (0). Pour cela, vous pouvez utiliser la commande !SB : 0 "M 10 C2 1+! SB en conséquence, une chaîne de 10 octets se déplacera d'un octet vers des adresses mémoire croissantes. La commande !SB est pratique pour travailler avec des chaînes de caractères (rappelons que chaque caractère est codé sur un octet). Il permet, par exemple, d'affecter la valeur d'une chaîne littérale explicitement spécifiée à un tableau d'octets. Pour spécifier une telle chaîne, utilisez un littéral de texte, c'est-à-dire une séquence de caractères entre guillemets, par exemple "TEXT LITERAL". Cette construction, lorsqu'elle est rencontrée dans un programme, provoque l'insertion de l'adresse de début et de la longueur de la chaîne d'octets contenant le texte entre guillemets dans la pile. Ces paramètres peuvent ensuite être utilisés par la commande !SB. Par exemple, le fragment "TABLE" 0 "TN! SB entraînera l'envoi du littéral TABLE au tableau TN. La commande SRCHB recherche dans une chaîne un octet spécifié. Paramètres : où b est l'octet dont la première occurrence doit être trouvée, a et n spécifient respectivement l'adresse du début et la longueur de la chaîne de recherche. Si n > 0, alors la recherche s'effectue de l'adresse a à l'adresse a + n-1 (dans le sens des adresses croissantes), si n<0, то поиск ведется с адреса a до адреса a+n+1 (в сторону убывания адресов). В результате выполнения этой команды в стеке оказывается значение d, равное смещению относительно адреса a до первого вхождения байта b. Если такое вхождение не обнаружено, то d=n. Примеры: #T "TEXTE" SRCHB #A "TEXTE" SRCHB #E "TEXTE" [# E, a, 4] 1- + -4 [# E, a + 3, -4] SRCHB [-2] Terminant l'examen des moyens de travailler avec les données, attardons-nous sur la question du stockage des données dans la mémoire externe d'un ordinateur, c'est-à-dire. sur des disques magnétiques. Dans le langage PARADISE il y a une commande SAVE<имя файла>pour enregistrer une copie de la mémoire principale du système sur le disque avec des objets définis par l'utilisateur. Dans ce cas, les zones mémoire allouées aux données par les opérations VAR, VCTR, ARR ne sont pas affichées sur le disque. En conséquence, lors du démarrage d'un système enregistré à partir du disque, les valeurs des données spécifiées ne sont pas définies (elles doivent être déterminées lors de l'exécution du programme). Dans la plupart des cas, cela est justifié, car il n'est pas nécessaire de dépenser de la mémoire disque pour stocker des variables de travail, des tampons, etc. Cependant, il existe des données dont les valeurs doivent être déterminées immédiatement après le démarrage du système à partir du disque. Un exemple est une variable qui stocke la vitesse d'échange de données avec un périphérique externe. Lors du passage à un autre taux de change, il suffit de modifier la valeur de cette variable sans apporter de corrections au programme. Une indication au processeur que les valeurs des éléments d'une structure de données doivent être sorties sur le disque par la commande SAVE est le préfixe FIX placé avant la définition de la structure, par exemple FIX VAR VITESSE 20 FIX BYTE VCTR TABL Travailler avec des structures de données définies de cette manière n'est pas différent de travailler avec des structures définies de la manière habituelle. Dans le langage PARADISE il existe un petit groupe de commandes destinées à contrôler le processeur DSPP, ou plutôt l'émulateur du processeur DSPP. La commande RESTART provoque un redémarrage du processeur. Dans ce cas, la pile est effacée, le message est émis DSSP version XX.XX.XX Gratuit XXXXXW et le processeur entre dans le mode d'attente d'entrée de commande. Cette commande est utile lors du débogage de programmes. Il est également exécuté lorsqu'une condition d'erreur se produit : l'index dépasse les limites du tableau, la mémoire libre est épuisée, etc. La commande \G permet de poursuivre l'exécution du programme après s'être arrêté sur un mot non défini. Si, lors de l'exécution d'une procédure, le processeur rencontre une référence à un mot non défini, il émet un message : arrête je ne sais pas<слово> . où point est l'invitation du processeur DSPP, signalant que le processeur est dans un état d'arrêt sur un mot non défini. Dans ce mode, vous pouvez exécuter n'importe quelle commande du processeur, comme en mode normal, lorsque l'astérisque est l'invite. Il existe deux manières de sortir de ce mode - soit en exécutant la commande \ G (le processeur continuera alors à exécuter la procédure interrompue, en sautant le mot non défini), soit par la commande RESTART. EXEC demande au processeur d'exécuter une procédure dont l'adresse se trouve au sommet de la pile. Pour obtenir l'adresse de la procédure, utilisez la commande "" (deux apostrophes) suivie du nom de la procédure. Par exemple, à la suite de la commande l'adresse de la procédure ABS sera poussée sur la pile. Ces commandes permettent de passer une procédure en paramètre à une autre procédure. L'opération SAVE déjà mentionnée appartient au groupe des commandes de contrôle du processeur.<имя файла>, prescrivant de sauvegarder une copie du système sur disque, ainsi que des commandes qui déterminent la source d'entrée des informations textuelles fournies à l'entrée du processeur. La source principale est le clavier d'affichage. CHARGER la commande<имя файла>bascule l'entrée vers un fichier disque portant le nom spécifié. Commande PF - prescrit d'entrer des commandes à partir du tampon de l'éditeur de texte. La commande TEXEC passe une chaîne de texte à l'entrée du processeur, dont les paramètres sont définis sur la pile. Lors de l'exécution des commandes contenues dans les sources spécifiées, la saisie bascule automatiquement sur le clavier d'affichage. Le flux d'instructions d'entrée perçu par le processeur peut notamment contenir des instructions pour définir des procédures et des données qui provoquent la compilation dans la représentation interne et stocker le corps de la procédure ou allouer de la mémoire pour les données spécifiées, ainsi que la saisie du nom du fichier compilé. procédure ou structure de données dans le dictionnaire DSPP. Le dictionnaire établit une correspondance entre les noms externes (utilisés dans le texte du programme) et les adresses des objets correspondant à ces noms dans la représentation interne. Lors du traitement de la définition d'une procédure ou d'une description d'un donné nommé, le processeur construit un dictionnaire, en y formant une nouvelle entrée de dictionnaire contenant le nom (plus précisément, les 7 premières lettres du nom) et l'adresse de la procédure corps ou descripteur de données qui est mappé à ce nom. Dans la programmation descendante, les corps de procédure peuvent contenir des références à des objets qui ne sont pas encore définis. Dans ce cas, les entrées du dictionnaire (en-têtes) sont formées dans le dictionnaire, marquées d'un signe d'ambiguïté. La commande UNDEF est utilisée pour afficher tous les noms non définis sur l'écran d'affichage. Au cours de la construction du dictionnaire, il est possible de former des sous-dictionnaires - des collections nommées d'entrées de dictionnaire. Un sous-dictionnaire combine généralement des procédures et des structures de données liées à une tâche. Pour éviter toute confusion entre les noms de sous-dictionnaires et d'autres objets de programme, le nom d'un sous-dictionnaire doit commencer par le caractère $. L'accès aux sous-dictionnaires pour leur extension ou leur utilisation peut être ouvert et fermé avec des commandes spéciales, qui incluent les suivantes (le nom $ v signifie tout sous-dictionnaire valide). GROW $ v - augmenter le sous-dictionnaire $ v, c'est-à-dire, jusqu'à ce qu'il en soit autrement, saisir les noms de toutes les procédures et données compilées dans le sous-dictionnaire $ v ; USE $ v - ouvre pour utiliser (pour rechercher des noms dedans) le sous-dictionnaire $ v; SHUT $ v - ferme la possibilité d'utiliser le sous-dictionnaire $ v ; ONLY $ v - ne rend disponible que le sous-dictionnaire $ v ; ANNULER - annuler le dernier UNIQUEMENT. Il y a aussi la commande ?$, qui imprime à l'écran les noms de tous les sous-dictionnaires de leur état - le sous-dictionnaire est ouvert ou fermé pour la recherche. Le dictionnaire, dont le nom est imprimé en haut, est toujours incrémenté. Les procédures de base du PRSP constituent un sous-dictionnaire nommé $ PRIME, ouvert à l'utilisation et à l'extension par défaut, c'est-à-dire s'il n'y avait pas de commande prescrivant l'extension d'un autre sous-dictionnaire. Supposons, par exemple, que l'opération ?$ ait imprimé l'état suivant des sous-dictionnaires. $ PRG ouvert $ PRIME ouvert $ EDIT fermé $ PRIME ouvert SYSTÈME fermé Cela signifie que $ PRG est actuellement ouvert pour extension et utilisation, $ PRIME est uniquement destiné à être utilisé et $ EDIT et SYSTEM ne sont pas disponibles. Notez qu'un sous-dictionnaire peut être constitué de plusieurs sections portant le même nom. Il existe des commandes pour supprimer un ensemble particulier d'entrées de dictionnaire du dictionnaire et, peut-être, des objets internes associés. Par exemple, la commande FORGET $ v supprime tous les noms entrés dans le dictionnaire (pas seulement dans le sous-dictionnaire $ v) après la dernière exécution de la commande GROW $ v ainsi que les objets indiqués par ces noms, et annule le développement de le sous-dictionnaire $ v qu'il a défini. La commande PROGRAM $ v fait la même chose que les commandes séquentielles FORGET $ v GROW $ v. La présence d'une telle commande au début de tout programme conduit au fait que lorsque le programme est recompilé, son ancienne copie sera supprimée et un dictionnaire sera formé pour stocker les objets de la nouvelle copie du programme. Par exemple, en effectuant l'opération FORGET $ PRIME sur un dictionnaire dont l'état a été montré ci-dessus, nous obtenons un nouvel état : $ EDIT fermé $ PRIME ouvert SYSTÈME fermé Lors de l'exécution de la commande FORGET, les noms des sections à supprimer sont affichés. Notez que le nom du sous-dictionnaire SYSTEM ne commence pas par $. Ceci est admissible, mais cela conduit au fait que l'application des commandes FORGET et RPOGRAM à ce sous-dictionnaire ne provoque aucune action (le sous-dictionnaire SYSTEM n'existe pas pour eux en quelque sorte). Du fait que dans le programme fini pour l'écrasante majorité des procédures, un appel par nom externe n'est pas requis, il est possible de supprimer leurs noms du dictionnaire tout en préservant les objets internes qui leur sont associés. La commande CLEAR $ v supprime tous les noms de toutes les sections du sous-dictionnaire $ v, à l'exception de ceux précédés du pré-préfixe :: (deux points) dans le texte du programme (lors de leur définition). Par exemple, suite à l'exécution par le processeur du fragment de programme suivant : ::: X + Y! + X; EFFACER $ EXAM seuls les noms X et X + resteront dans le sous-dictionnaire $ EXAM, l'entrée du dictionnaire Y sera supprimée (bien que la variable correspondant au mot Y dans la représentation interne restera). Le principal moyen d'interaction entre l'utilisateur et le DSPP est le terminal, qui, en règle générale, est un écran cathodique avec un clavier. Le terminal est utilisé pour la saisie initiale, l'édition et le débogage des programmes, la préparation des données et toute la gestion du système. Les programmes et les données, ainsi que le chipboard lui-même, sont enregistrés sous forme de fichiers sur des disques et peuvent être imprimés sur une imprimante. Les outils suivants sont disponibles pour contrôler les E/S dans l'ensemble des procédures de base du DSRP. La programmation du fonctionnement du terminal est assurée par des commandes d'entrée et de sortie de chiffres, de lettres individuelles et de séquences de lettres (lignes), ainsi que par certaines commandes supplémentaires. La commande TIB (Terminal Input Byte) initie une boucle en attente d'un appui sur une touche du clavier du terminal. Lorsqu'une touche est enfoncée, le code à 8 bits de la lettre correspondante est poussé sur la pile en tant qu'octet le moins significatif du sommet, les 3 octets les plus significatifs contenant des zéros. Une copie de la lettre ainsi saisie s'affiche à l'écran. Il existe également une commande TRB (Terminal Read Byte) qui diffère de TIB en ce que le fait de pousser le code de la lettre saisie sur la pile ne s'accompagne pas de l'affichage de cette lettre sur l'afficheur. La commande TIN (Terminal Input Number) lance un cycle d'entrée dans la pile et d'affichage du numéro tapé au clavier sur l'écran. Le nombre entré doit être une séquence de nombres, qui peut commencer par un signe moins et se terminer Chaque commande TIN entre un numéro. S'il est nécessaire de saisir une séquence de chiffres sur une ligne, il faut les séparer en appuyant sur la touche Une séquence contenant n caractères tapés au clavier est introduite dans la mémoire de l'ordinateur sous forme de n octets situés à des adresses séquentiellement croissantes, à partir de l'adresse a, à l'aide de la commande TIS (Terminal Input String), avant laquelle l'adresse a et le nombre de les lettres n sont poussées sur la pile ... Par exemple, déclarons un vecteur d'octets X de longueur suffisante. Vous devez saisir 9 caractères en attribuant leurs valeurs aux éléments de ce vecteur, en partant de l'élément zéro : De même, la commande TOS définit la sortie d'une séquence de n octets avec l'adresse de début a : La sortie vers le terminal des éléments de texte directement inclus dans le programme est fournie par la construction ."<текст>" Par exemple, pour que lorsqu'un certain fragment du programme est exécuté, le texte ENTER VARIANT NUMBER apparaisse à l'écran, le fragment doit contenir l'entrée "ENTER VARIANT NUMBER". La commande TON (Terminal Output Number) affiche le numéro extrait de la sous-pile et la longueur du champ de sortie doit être spécifiée en haut. Le nombre affiché est aligné sur le bord droit du champ, les positions libres à gauche sont remplies d'espaces, et si la longueur du nombre dépasse la longueur de champ spécifiée, la gauche est coupée. En mode E/S décimal, les nombres négatifs commencent par un signe moins. La commande TOB (terminal output byte) imprime la lettre dont le code est spécifié par l'octet de poids faible du haut de la pile. La profondeur de la pile est diminuée de 1. Il existe également des commandes qui contrôlent directement le curseur d'affichage : CR - sauter au début d'une nouvelle ligne, SP - espace, c'est-à-dire déplacer d'une position vers la droite. La commande BELL produit un bip court ("cloche"). Parfois, lors de la communication avec le terminal, il est nécessaire de vérifier si la touche a déjà été enfoncée et si l'affichage a déjà terminé la commande de sortie précédente. Cela peut être fait avec les commandes TTI (Terminal Test Input) et TTO (Terminal Test Output), qui laissent le drapeau 1 sur la pile si l'événement spécifié s'est produit, et 0 sinon. Les commandes de sortie d'imprimante sont similaires aux commandes de sortie de terminal et sont basées sur un mnémonique similaire, dans lequel les caractères LP (Line Printer) ont remplacé TO ou ajoutés en tête. Par exemple, LPCR - sauter au début d'une nouvelle ligne, LPSP - espace, LPN - sortir un nombre de la sous-ligne dans le champ spécifié par le sommet, LPB - sortir un caractère, LPS - sortir une chaîne de caractères. Il existe également la commande [N] LPT, qui déplace la tête d'impression à la position N de la ligne imprimée, et la commande LPFF, qui alimente une feuille de papier. Pour imprimer un texte explicitement spécifié, il est pratique d'utiliser un littéral de texte et la commande LPS, par exemple : "TABLEAU DES VALEURS DE FONCTIONNEMENT" LPS Lors de la programmation des périphériques, il devient nécessaire de gérer les interruptions. En DSPP, ce traitement est programmé comme suit. Le programme destiné à traiter les interruptions est une procédure PRSP normale, avant la définition de laquelle il y a un pré-préfixe INT, par exemple INT : A ! 1+ I ; Le préfixe INT garantit que l'état du processeur est enregistré pendant l'interruption et restauré lorsque l'interruption est traitée. Pour lier un programme pièce à une interruption spécifique, utilisez la commande LINK : <адрес вектора>LIEN<имя процедуры>lorsqu'il est exécuté, un appel à la routine de gestion des interruptions est écrit le long du vecteur correspondant. La commande LINK peut effectuer à la fois l'enchaînement statique d'une procédure avec une interruption, qui intervient au moment de la compilation du programme, et dynamique, lors de l'exécution du programme. Une interruption de processeur est la manière dont le système est informé d'un événement qui s'est produit dans le monde extérieur. Des événements nécessitant un traitement immédiat peuvent également se produire dans le programme. C'est ce qu'on appelle des situations exceptionnelles. Exemples de telles situations : division par zéro, erreur de communication avec l'appareil, fin du fichier d'entrée, etc. Dans le DSPP, les exceptions sont capturées à l'aide d'interruptions de commande. Une interruption de commande est une opération nommée appelant une procédure de réponse et est déclarée comme suit : PIÈGE<имя вызова> <конечная реакция> Par exemple: PIÈGE S1 "Situation S1." Dans le premier cas, la procédure X est la réaction finale à l'interruption S ; dans le second, lorsqu'une interruption S1 se produit, le terminal recevra un message : Situation S1. Le programme, au cours de l'exécution duquel l'interruption peut se produire, peut y définir sa réaction à l'aide de la commande intercept. Le DSSP prévoit deux types d'interceptions : ON et EON. Les commandes d'interception ne peuvent être utilisées que dans les procédures et ont le format : AU<имя прерывания> <реакция> EON<имя прерывания> <реакция>Par exemple: : A ... ON S. "Interruption S" ...; : A1 ... EON S1 ABC ...; ON et EON définissent différents types de réactions. Si une nouvelle réaction est définie par la commande ON, lorsqu'une interruption se produit, une procédure de réaction est exécutée, après quoi le programme interrompu continue de s'exécuter. Si la réaction est définie par la commande EON, la pile d'opérandes prend d'abord la profondeur qu'elle avait au moment de l'exécution d'EON, puis la réaction est effectuée et, après son achèvement, l'exécution de la procédure dans laquelle la commande EON a été utilisé est immédiatement résilié. Regardons quelques exemples. La procédure M entre des caractères à partir du clavier du terminal et vérifie s'il s'agit d'un chiffre. Si le caractère saisi n'est pas un chiffre, l'interruption ND est déclenchée. TRAP ND. "Pas un chiffre." : MRP M1; : M1 TRB [B] C # 0< C2 #9 >& 0 SI + ND [B] TOB; La réponse finale à une interruption ND est le message : Pas un chiffre. Si M est appelé depuis la procédure P1, qui a sa propre réponse à l'interruption ND : P1 ON ND PR1 M ; : PR1 [B] CR. "Erreur." D # 0 [# 0] ; puis lors de la saisie d'un caractère non numérique, l'interruption ND sera traitée par le programme de réaction PR1 de type ON, ce qui fera sortir le message suivant sur une nouvelle ligne : Erreur. La lettre saisie sera remplacée par la lettre 0, après quoi M continuera à fonctionner. Si M est appelé depuis la procédure P2 : P2 EON ND PR2 M ; : PR2 CR. "Erreur. Fin de saisie." ; puis lors de la saisie d'un caractère non numérique, l'interruption ND sera traitée par le programme de réaction PR2 de type EON, ce qui fera sortir le message suivant d'une nouvelle ligne : Erreur. Fin de l'entrée., Puis P2 sortira. La pile d'opérandes sera alors vide. Si nécessaire, une interruption peut être déclenchée à nouveau dans le programme de réaction, l'étendant ainsi aux programmes de niveau supérieur. Dans ce cas, l'interruption sera gérée soit par le programme spécifié dans la commande d'interception dans la procédure d'insertion, soit par la réaction finale. Par exemple, si vous modifiez PR2 comme suit : : PR2 CR. "Erreur. Fin de saisie." ND ; alors le message délivré au terminal sera : Erreur. Fin de l'entrée. Pas un numéro. Le DSPP dispose de plusieurs interruptions de commande intégrées, dont la réaction peut être fournie dans les programmes utilisateur. Assalam alaykum wa rohmatullahi wa barakatuhu ! Wa aleikum salam wa rahmatullahi wa barakatuh ! At-Tabarani à al-Awsat, selon Abu Huraira, rapporte : Cheikh al-Albani l'a amené à Silsil ad-da'ifa au numéro 161, en disant : « Ce hadith est fictif (maudu'). En réalité, il n'y a pas un seul hadith fiable qui explique quelle langue parlera les habitants du Paradis, il est donc nécessaire de garder le silence et de ne pas se plonger dans des conversations sur cette question, en laissant la connaissance à Allah Tout-Puissant, et de ne faire que ce qui va conduire à l'accomplissement de ces actes qui profiteront à l'autre monde ! La langue est un système de signes qui permet de passer du sens et du sens d'un concept à sa désignation. L'homme est une créature verbale et, contrairement aux animaux, communique avec les siens en utilisant le langage. Parfois, ils parlent du "langage des animaux", mais il est clair qu'une telle expression est conditionnelle - en termes de richesse et de capacités, le langage des animaux n'est pas similaire à celui des humains. Les anges, en revanche, n'ont pas du tout besoin d'une langue pour communiquer - il est difficile de les imaginer parler russe ou anglais. Les fonctions du langage peuvent être différentes - en plus de transmettre des informations, il aide à exprimer des sentiments et des évaluations. La langue de l'Église est la langue de la prière, de l'adoration et de l'Écriture. Dans certaines religions, les textes sacrés existent initialement dans une langue particulière et sont considérés comme fondamentalement intraduisibles. Ainsi, le Coran musulman a été à l'origine composé en arabe. De plus, les musulmans croient que c'est ainsi que ce livre a été créé au début des temps. Les scribes juifs étaient également enclins à l'idée de la possibilité de textes sacrés uniquement en hébreu. Ce n'était pas le cas avec l'Écriture chrétienne depuis le début. Au IIIe siècle av. la soi-disant "traduction des soixante-dix" - la Septante - la traduction de l'Ancien Testament en grec a été réalisée. De plus, certains chercheurs pensent que c'est la Septante qui a joué le rôle de l'Écriture Sainte à l'époque inter-testamentaire. C'est l'existence de la Septante qui est devenue le principal argument en faveur de la traduisibilité de principe de l'Écriture. Il y en a cependant un encore plus fort. Il est maintenant considéré comme prouvé que le Christ a parlé aux apôtres en araméen. Mais les rédacteurs des évangiles n'ont pas hésité à transmettre ces conversations en grec. Maintenant, il y a une direction scientifique - la reconstruction linguistique. Leurs compilateurs essaient de comprendre comment ces dialogues sonnaient dans l'original. Mais cela fait toujours l'objet d'études scientifiques. Lors de la traduction d'une langue dans une langue, des problèmes surviennent parfois car les langues ne sont pas grammaticalement identiques. Les significations et les nuances des mots dans différentes langues sont également différentes. Par exemple, l'expression « le ciel est un endroit chaud et frais » montre clairement que l'Écriture a été créée dans des pays au climat chaud, où la « fraîcheur » est plutôt agréable. En russe, de telles associations n'apparaîtraient guère. Et le verbe « se détendre » dans le sens de « se reposer », « passer un bon moment » est entré en russe comme papier calque de l'hébreu au grec. L'Écriture a été apportée à nos ancêtres d'une manière non russe. Cyril et Méthode - les Grecs de Solunsk - ont développé une nouvelle langue écrite basée sur la langue parlée des Slaves de Solunsk. Dans le monde, de nombreux peuples utilisent des langues qui n'ont pas de langue écrite. Tant qu'on parle de la vie de tous les jours, il n'y a pas de problèmes. Mais, dès qu'un texte religieux ou un traité philosophique doit être traduit dans une telle langue, la langue doit être améliorée, ce qui a été fait par Cyril et Méthode. Si nous supposons qu'il y a quelques milliers d'années, les tribus slaves étaient plus faciles à s'entendre que les peuples slaves modernes, alors nous aurons raison - les langues étaient plus proches. Mais cela ne signifie pas que la traduction des Écritures, faite par Cyrille et Méthode, était plus compréhensible pour les habitants de Kiev et de Novgorod - la langue littéraire écrite était différente. C'est peut-être une caractéristique de la situation russe, puisque la langue littéraire russe est plus proche du slavon d'église que du dialecte de Moscou. En fait, toute la langue slave de l'Église est entrée en russe comme un « grand calme ». Par exemple, même les participes modernes - tels que pleurer, courir - sont formés précisément selon le modèle slave d'église - en vieux russe, ce sera "pleurer", "courir". Parfois, les anciens homologues russes abandonnaient complètement - « bon » et « bologo » dans le nom « Bologoye » ; "Shelom", qui n'est que dans les épopées, contrairement au "casque". Dans la Russie antique, il y avait une situation de diglossie. Ce n'est pas comme le bilinguisme. La diglossie est l'utilisation de deux langues en parallèle dans la société. Par exemple, au XIXe siècle, le russe et le français étaient utilisés. Le français était la langue de la haute société, mais, en principe, n'importe quel texte pouvait être traduit. En diglossie, les langues ne se chevauchent pas en termes d'usage. Ils parlaient en vieux russe, en vieux russe, ils pouvaient écrire une note de ménage. Mais ils priaient en slavon d'église. Cette situation existait avant Pierre, au XVIIIe siècle elle s'effondre peu à peu. Maintenant, la science et la littérature pourraient se développer en russe, mais en slavon d'église, seules les prières existent encore. Traduisez en une publicité en slavon d'église - et cela ressemblera à une blague ou à un blasphème. Nous vivons à une époque unique. Dans la Russie tsariste, la Bible pouvait être lue en russe, dans la Russie ancienne, il était possible de l'écouter en slavon. Mais la plupart des gens étaient analphabètes ou pas assez instruits pour lire et percevoir les Écritures. À l'époque soviétique, tout le monde était devenu alphabétisé, mais il n'y avait pas de texte de l'Écriture. L'alphabétisation est toujours préservée et des textes sont disponibles. En plus des Écritures elles-mêmes, nous sommes invités à maîtriser d'autres textes slaves - des prières aux services divins. Certes, la traduction existante en russe est quelque peu difficile à comprendre. Au 19ème siècle, n'ayant pas d'analogues, les traducteurs traduisaient souvent les slavismes en traduction. Ainsi, l'expression « Je suis le bon berger » a migré vers la traduction. Et voici quelques difficultés. Une traduction littérale du grec sonnerait : « Je suis un bon berger », mais une telle traduction est perçue comme faible. En revanche, le sublime "pasteur" est désormais perçu par un simple auditeur plutôt comme un "prêtre". Cependant, il faut admettre qu'une traduction littérale en russe de nombreux dictons bibliques est impossible - l'expression "par la bouche d'un enfant dit la vérité" - car un dicton philosophique ne sera pas perçu. Mais en général, la perception du texte slave de la Bible est plus entravée par un manque de compréhension du sens, et non des mots. Une difficulté distincte est celle des constructions grammaticales. Par exemple, il y a un certain nombre d'améliorations qui viennent du grec. « Pardonner les péchés et les transgressions » signifie simplement pardonner tous les péchés. Les constructions du type « J'étais en colère contre la colère », « J'aimais avec amour » sont similaires. Lors de la traduction de textes sacrés dans d'autres langues, des problèmes surviennent également (bien que les peuples dans les langues desquels les Écritures n'ont pas encore été traduites représentent peut-être 5℅ de la population mondiale). C'est-à-dire que le travail que Cyril et Méthode ont fait pour les Slaves continue. Cyril et Méthode n'étaient pas les premiers - avant cela, il y avait des traductions en éthiopien, gothique. Après Cyrille et Méthode, Etienne de Perm traduisit les Écritures en langue zyryenne. Chaque traduction est-elle considérée comme un texte sacré ? Non, mais seulement dans la mesure où cela est accepté dans les communautés ecclésiales. Par exemple, la traduction synodale en tant que traduction liturgique n'est pas interdite, mais pas acceptée. Mais il est utilisé comme tel par les protestants, par exemple les baptistes russes. Il y a même des courants modernes du protestantisme qui croient que le texte biblique devrait être accessible à tous. Des bandes dessinées basées sur des thèmes bibliques sont également publiées. Il n'y a aucun problème avec le texte du Nouveau Testament - sa source est connue en grec. Mais la base de la traduction synodale de l'Ancien Testament était le texte hébreu. Des fragments de la traduction grecque n'ont été insérés que lorsque les divergences étaient fondamentales. Dans la version moderne, ce serait bien d'avoir deux traductions - à la fois des textes massorétiques hébreux et du grec. Ce serait pratique pour ceux qui ne connaissent pas les deux langues. Après le discours, plusieurs questions ont été posées à l'archiprêtre Alexandre : – Quelle langue parlait Adam ? - C'est dur à dire. D'une part, la langue change pendant qu'elle est vivante. Mais nul ne sait s'il ne s'agissait pas d'une nouvelle propriété des langues apparue après la construction de la Tour de Babel. Mais, en tout cas, la langue d'Adam ne ressemblait probablement à aucune des langues existantes, y compris l'hébreu. – Y a-t-il une controverse sur la traduction du service en russe ? - Cette idée a été discutée avant même la révolution, et a été en partie compromise par les rénovateurs. Ils n'ont pas tous servi en russe, mais l'idée a été soutenue par eux. La traduction de la Bible en russe n'a pas été facile, même si l'idée du Philarète métropolitain qu'il fallait traduire à la fois de l'hébreu et du grec était une sage décision. Bien que cela ne nous ait pas donné de traductions scientifiques dans les deux langues. Il existe des cas individuels d'utilisation de la langue russe - la prière des anciens d'Optina et l'akathiste "Gloire à Dieu pour tout" ont été écrites à l'origine en russe. Il y a tellement d'autres traductions, et il y aura tellement de nuances dans leur mise en œuvre qu'il est plus facile de russifier quelque peu les textes que de les traduire. Ce processus se déroule spontanément depuis longtemps. Parfois, des incidents surviennent : par exemple, dans le « Rite des noces », le duel est parfois remplacé de manière inattendue par le pluriel, et chez les akathistes modernes, il est utilisé de manière incohérente. – Comment la Divine Providence participe-t-elle à la formation des différentes langues ? - Le langage existe en dehors de la volonté humaine. Une personne peut créer l'espéranto, mais les langues naturelles existent selon leurs propres lois. Cyrille et Méthode ont traduit en slavon d'église par inspiration d'en haut, mais aussi selon le modèle qui existait à cette époque. Par inspiration d'en haut, en écrivant les évangiles en grec, les apôtres ont posé l'idée de traduire l'évangile. Préparé par Daria Mendeleeva Photo de Dmitry Kuzmin QUESTION:
Assalam alaikoum aha ! Ici, je suis tombé sur cet article. Si je ne me trompe pas, vous avez écrit l'inverse. Si ce n'est pas difficile, vous pouvez à nouveau commenter cet article. Musulman. L'arabe est la langue du Coran. Il était l'élu parmi toutes les langues du monde, et il a des propriétés extraordinaires. Cette langue est aussi la langue du Prophète Muhammad (paix et bénédiction d'Allah sur lui). Cette langue est riche et aucune des langues du monde ne peut rivaliser avec elle. Il a une influence spirituelle et physique sur le locuteur de cette langue. Auparavant, les Arabes organisaient des concours de poésie, mais lorsque le Prophète (s.a.s.) a reçu la Révélation, les Arabes ont été tellement étonnés de la merveilleuse expressivité de la langue, et même certains pensaient que le Coran avait un effet magique sur une personne. Si quelqu'un veut corriger un mot ou une lettre du Coran, toute l'harmonie du Livre divin sera violée. Pas un seul mot du Coran ne doit être changé, sinon le sens et la phonétique changeront. Nous savons que certains mots ont tendance à devenir obsolètes avec le temps, et nous ne les utilisons pas. Et la langue du Coran n'a pas perdu de sa pertinence depuis 1439 ans... J'enseigne le Coran depuis plus de 10 ans et à ce jour je n'ai rencontré aucun de mes élèves pour me poser une question : « Pourquoi étudions-nous le Coran ? D'où vient-il? Quels avantages possède-t-il ? Qu'est-ce qui le différencie de la lecture de gauche à droite ?" De jour en jour, le nombre de personnes qui souhaitent étudier l'alphabet arabe et les règles du tajwid augmente, afin qu'ils puissent plus tard lire le Coran à partir de l'original. Mais peu de gens pensent à la réponse aux questions ci-dessus. Et enfin, quand je leur parle des avantages du Coran, de ses avantages, beaucoup commencent à approfondir cela. La langue arabe a 29 lettres. Les sons se forment au bord du larynx, au milieu du larynx, de la poitrine, entre la racine de la langue et la cavité buccale. Les sons de la langue arabe "nettoient" la cavité buccale et sont moins sensibles aux maladies. De plus, l'arabe est un bon orthophoniste. Il guérit le zézaiement et la mauvaise prononciation de la lettre "r". Cette langue aide également les malvoyants. Parce que lire le texte arabe de gauche à droite améliore l'appareil visuel d'une personne et la détend. La forme ovale et ronde des lettres est également bonne pour la psyché. Toutes les lettres de l'alphabet arabe sont des consonnes. Il n'y a pas de lettres spéciales pour les voyelles. Une distinction est faite entre les voyelles courtes et longues. Les voyelles courtes sont transmises par écrit à l'aide de voyelles - exposants et indices. De plus, sur 28 lettres, 22 lettres sont connectées des deux côtés et 6 lettres sont connectées uniquement à droite. Le Coran nous est parvenu depuis 23 ans sans distorsion. Le Coran est le dernier livre divin, et il n'y aura pas d'autres livres après lui. Il a été envoyé à toute l'humanité. Les lois du Coran resteront en vigueur jusqu'au jour du jugement et ne changeront pas. Le Coran est un éternel, grand miracle du Tout-Puissant, donné au Prophète Muhammad (s.a.s.). Lire le Coran, c'est adorer. Je conseille à tout le monde de lire ce livre incroyablement merveilleux tous les jours et d'en connaître le sens. Dépêchez-vous d'apprendre à lire et à parler avec votre Créateur. Allah nous accordera d'être résidents de Jannat et de parler la langue arabe, qu'Il a Lui-même choisie. Dilyar Bektayeva, ustaz d'Aktobe régional mosquée centrale "Nur Kasyr" http://nurgasyr.kz/index.php/ma-alar/1826-yazyk-zhitelej-dzhannata
RÉPONSE:
wa aleikum en tant que frère salam ! Comme elle, les « fausses ustaz » indigènes et ignorantes devraient être éloignées des musulmans, afin de ne pas les induire en erreur. Une fois dans la mosquée d'Aktobe, de telles absurdités sont répandues et des enseignants ignorants sont gardés, c'est peut-être pourquoi il y a tant de sectaires extrémistes dans cette ville. Ni le Coran ni la Sunna ne contiennent même une allusion lointaine que la langue arabe sera une langue commune pour tous les habitants du paradis. Pensez par vous-même à la façon dont les représentants d'autres nationalités communiqueront entre eux au paradis s'ils ne connaissent pas la langue arabe ?! Auparavant répondu à une question similaire :Données nommées
Travailler avec la mémoire par adresses physiques
Opérations supplémentaires pour travailler avec les données et la mémoire
Commandes de contrôle du processeur
Commandes de dictionnaire
Commandes E/S
Gestion des interruptions et des exceptions
"La langue arabe est la langue des habitants du Paradis !" (Sens approximatif)
Chers frères, je vous demande de clarifier la question concernant ce hadith, est-il fiable ? En général, ces mots sont-ils les mots du prophète Mahomet, alayhi salty wa salam ?
barakALLAHU fikum wa jazakumu Allahu hayran!
« Le Messager d'Allah (paix et bénédiction d'Allah sur lui) a dit : "Je suis arabe, Kuran est en arabe et la langue des manoirs du paradis sera l'arabe."
On a demandé à Sheikhul-Islam Ibn Taymiyyah (qu'Allah lui fasse miséricorde) : « Quelle langue parlera-t-on le Jour de la Résurrection ? Allah Tout-Puissant parlera-t-il aux gens en arabe ? Et est-il vrai que la langue des habitants de l'Enfer est le persan et que les habitants du Paradis sont l'arabe ?
A quoi il répondit : « Louange à Allah, le Seigneur des mondes ! On ne sait pas quelle langue les gens parleront ce jour-là, comment et quelle langue leur Seigneur leur parlera, Il est grand et glorieux. Ni Allah Tout-Puissant, ni son Messager, paix et bénédictions sur lui, ne nous ont rien dit à ce sujet, et il n'est pas non plus fiable que la langue des habitants de l'Enfer sera le persan, et la langue des habitants du paradis sera l'arabe. Et nous ne savons pas qu'à cette occasion parmi les Compagnons, qu'Allah les agrée, il y eut un quelconque désaccord. Au contraire, ils se sont abstenus de le faire, car en parler ne sert à rien. Cependant, il y avait un désaccord parmi les générations suivantes concernant cette question. Certains ont dit qu'ils communiqueraient en arabe, d'autres ont dit que cela ne s'applique pas aux habitants de l'Enfer, puisqu'ils répondront en persan et c'est leur langue en Enfer. D'autres encore - que les gens communiqueront en assyrien, car c'est la langue d'Adam, dont toutes les autres langues sont originaires. Quatrièmement, que cela ne s'applique pas aux habitants du Paradis, puisqu'ils communiqueront en arabe. Cependant, aucun d'entre eux n'a d'argument en faveur de leurs propos, ni de la raison, ni des sources de la charia, mais ce ne sont que des déclarations exemptes de toute preuve. Allah Tout-Puissant sait mieux ! " Voir Majmu'ul-Fataawa 4/299.L'Écriture peut-elle être traduite ?
Est-ce vraiment au paradis–du froid?
Tous les Slaves comprenaient-ils la Bible ?
Les langues sont proches et... parallèles
Prêtre ou berger ?
Traductions sacrées et profanes
Réponses aux questions