RASM v0.96


roudoudou Z80 assembler

Table des matières

Introduction
Fonctionnalités
Installation
Compilation
   - Compilation Linux
   - Compilation Windows
   - Compilation MorphOS
Comportement
Ligne de commande
   - Options de noms de fichiers
   - Options d'export sur fichier EDSK
   - Options d'export sur fichier snapshot
   - Options de symboles
   - Options de dépendances
   - Options de compatibilité
   - Options de développeur (usage interne)
Format du code source
   - Généralité
   - Commentaires
   - Valeurs litérales
   - Caractères autorisés
   - Fichiers
   - Labels
   - Labels de proximité
   - Labels locaux
   - Tags spécifiques aux labels ou structures
      {BANK}
      {PAGE}
      {PAGESET}
      {SIZEOF}
   - Coloration syntaxique dans VIM
Expressions
   - Opérateurs de calcul
   - Priorité d’exécution des opérateurs
Variables
   - Statiques
   - Dynamiques
Directives mémoires
   - ALIGN
   - BANK
   - BANKSET
   - LIMIT
   - ORG
   - PROTECT
   - WRITE DIRECT
Directives de définition de données
   - CHARSET
   - DEFB
   - DEFW
   - DEFI
   - DEFR
   - DEFS
   - EQU
   - STR
   - STRUCT
Directives d'import et de compression
   - INCLUDE
   - INCBIN
   - INCL48, INCL49, INCLZ4, INCZX7, INCEXO
   - LZ48, LZ49, LZ4, LZX7, LZEXO
   - LZCLOSE
Directives de code conditionnel
   - ASSERT
   - IF IFNOT THEN ELSEIF ELSE ENDIF
   - IFDEF, IFNDEF
   - IFUSED, IFNUSED
   - MACRO
   - PRINT
   - FAIL
   - REPEAT, REND, UNTIL
   - SWITCH, CASE, DEFAULT, BREAK, ENDSWITCH
   - STOP
   - WHILE, WEND
Directives de sortie fichier
   - AMSDOS
   - BREAKPOINT
   - BUILDCPR
   - BUILDSNA
   - RUN
   - SAVE
   - SETCPC
   - SETCRTC
Directives de compatibilité
   - LIST, NOLIST, LET
Jeu d'instruction
Limitations
Introduction
Lors de la création de ma démo CRTC³, les assembleurs existants ont tous rapidement montré leurs limites, que ce soit en termes de rapidité d'assemblage ou de fonctionnalités offertes. En effet, le projet final analyse plus de 250'000 mots (hors commentaires), 35'000 labels et 60'000 expressions. Il fallait donc en priorité un assembleur qui soit rapide et lui ajouter au minimum des fonctionnalités que n'ont pas les autres: support natif des cartouches, disquettes ou snapshot Amstrad, espaces mémoires multiples, calculs flottants, compressions les plus courantes intégrées (afin de s'éviter par exemple de fastidieux export/imports de symboles), etc.

Il y a 18 ans, j'avais programmé un petit assembleur. Je ne m'en étais pas servi à l'époque car il était limité. J'en ai néanmoins repris le principe d'assemblage mono-passe.

Rasm utilise des concepts éprouvés (arbres de Merkel, nombreux caches, allocations groupées) et surtout une conception linéaire (la récursivité tue les performances). Les performances d'assemblage sont extrêmement rapides en conditions réelles sur de gros projets, si bien que certaines optimisations n'ont même pas été faites.

Aujourd'hui Rasm est utilisé sur plusieurs gros projets:
 - Ghost'n Goblins par Golem13
 - Arkos Tracker II par Targhan de façon intégrée au logiciel


Rasm est diffusé sous licence MIT.
Fonctionnalités
Installation
Rasm est un exécutable indépendant, il s'utilise tel que, sans installation aucune.
Compilation
Compilation Linux avec GCC ou Clang
cc rasm_v096.c -O2 -lm -lrt -march=native
mv a.out rasm
strip rasm
Compilation Windows avec Visual Studio
cl.exe rasm_v096.c -O2
Compilation DOS ou Windows 32 bits avec Watcom
# do not use -s or -ox option, this will cause a fatal stack issue wcl386.exe rasm_v096.c -6r -6s -fp6 -d0 -k4000000 -obmiler
Compilation MorphOS (ixemul)
ppc-morphos-gcc-5 -O2 -c -o rasm rasm_v096.c
strip rasm
Comportement de Rasm (généralités)
Rasm essaie d'être simple d'utilisation. En ce sens il va produire des noms de fichier par défaut, déterminer la quantité de mémoire à enregistrer ou même créer un fichier cartouche si les banques ROM ont été sélectionnées lors de l'assemblage.

Rasm permet l'utilisation de plusieurs ORG au sein d'un même espace mémoire. Par contre il n'autorise pas de ré-écrire sur les mêmes adresses mémoire. À chaque nouveau ORG, Rasm contrôle qu'aucune zone de code écrite ne se chevauche.

Si vous avez besoin de générer plusieurs morceaux de code à la même adresse, vous avez deux possibilités. Soit vous utilisez le deuxième paramètre de la directive ORG pour écrire ce code ailleurs, soit vous pouvez créer à tout moment un nouvel espace mémoire avec la directive BANK

Dans la mesure du possible, Rasm essaie d'afficher des messages d'erreurs afin de vous orienter vers la solution syntaxique convenable.

Rasm va d'abord pré-traiter le fichier à assembler pour enlever les espaces superflus, les commentaires, vérifier les quotes, que les caractères utilisés soient conformes et enfin transformer certaines instructions en d'autres pour convenance interne. Par exemple les opérateurs Maxam XOR, AND, OR et MOD seront convertis en un seul caractère approchant la syntaxe du C.

Lorsqu'une directive de lecture ne fait pas référence à un chemin absolu, le répertoire racine au chemin relatif est celui du fichier en cours.

Ligne de commande
La syntaxe de base est: rasm.exe <fichier à assembler> [options]

Exemple: rasm.exe monfichier.asm
Options relatives aux noms de fichiers
-o <radix de fichier> définir un nom commun pour chaque type de fichier en sortie, quel que soit son type (.bin, .cpr, .sym). La valeur par défaut est “rasmoutput”
Exemple:
rasm.exe test -o grouik -s
Pre-processing [test.asm]
Assembling
Write binary file grouik.bin (25 bytes)
Write symbol file grouik.sym (10 bytes)
-ob <nom de fichier binaire> définir le nom complet pour le fichier de sortie binaire.
-oc <nom de fichier cartouche> définir le nom complet pour le fichier de sortie cartouche.
-oi <nom de fichier snapshot> définir le nom complet pour le fichier de sortie snapshot.
-os <nom de fichier symbole> définir le nom complet pour le fichier de sortie des symboles.
-ok <nom de fichier breakpoint> définir le nom complet pour le fichier de sortie des points d'arrêt.
-I<répertoire dans lequel chercher les fichiers à inclure> définir le répertoire d'inclusion des fichiers, plusieurs options -I cumulables.
-no désactiver toute écriture de fichier
Options d'export sur fichier EDSK
-eo   écraser les fichiers sur l'image disque si il y a conflit de nom.
Options d'export sur fichier snapshot
-v2 Créé un snapshot version 2 (export par défaut en version 3)
-sb Exporte les points d'arrêt (breakpoints) dans le fichier snapshot (compatible avec les formats Winape et ACE), uniquement avec la version 3+
-ss Exporte les symboles dans le fichier snapshot (compatible avec les formats Winape et ACE), uniquement avec la version 3+
Options relatives aux symboles
-s exporter les symboles au format Rasm
Exemple de fichier produit:
LABEL1 #0 B0
LABEL2 #1 B0
LABEL3 #2 B0
LABEL4 #4 B0
-sp exporter les symboles au format Pasmo
Exemple de fichier produit:
LABEL1 EQU 00000H
LABEL2 EQU 00001H
LABEL3 EQU 00002H
LABEL4 EQU 00004H
-sw exporter les symboles au format Winape
Exemple de fichier produit:
LABEL1 #0
LABEL2 #1
LABEL3 #2
LABEL4 #4
-sl option additionnelle aux trois précédentes qui permet d'exporter aussi les symboles locaux aux macros ou boucles de répétition.
-sv option additionnelle aux trois précédentes qui permet d'exporter aussi les variables.
-sq option additionnelle aux trois précédentes qui permet d'exporter aussi les alias EQU.
-sa option équivalente à -sl -sv -sq
-ss exporter les symboles dans un snapshot
-eb exporter les points d'arrêt
-l <fichier label> importer un fichier de labels pour l'assemblage au format Rasm, Sjasm, Pasmo ou Winape. La détection du format est automatique.
-D<var>=<valeur> option pour définir une variable depuis la ligne de commande. Exemple: rasm.exe -DTRUC=1 va définir la variable TRUC à 1.


Note 1: Il est possible de cumuler plusieurs fichiers de symboles en cumulant les options -l
rasm.exe test -l import1.sym -l import2.sym -l import3.sym
Note 2: L'émulateur Arnold est compatible avec Rasm et Pasmo.
Note 3: L'émulateur Winape n'est pas capable de prendre en charge des labels trop longs!
Options de compatibilité
-depend=make
Exporte toutes les dépendances du programme sur une seule ligne (pour une utilisation en makefile).

-depend=list
Exporte toutes les dépendances du programme, une par ligne.

Si un nom de fichier binaire est spécifié (option -ob) alors il sera ajouté en première position.
Options de compatibilité
            
-m compatibilité Maxam
  • calculs réalisés en entiers 16 bits non signés avec un mauvais arrondi
  • les comparaisons se font avec l'opérateur = simple
  • la priorité des opérateurs est simplifiée (voir tableau)
-ass compatibilité AS80
  • calculs réalisés en entiers 32 bits avec un mauvais arrondi
  • les déclarations de type DEFB,DEFW,DEFI ou DEFR multiples ont pour référence d'adresse l'adresse du premier octet produit et non l'adresse de l'octet courant. Cette spécificité d'AS80 fait que deux DEFB ne produisent pas la même chose qu'un seul DEFB avec deux valeurs (quand la référence $ est utilisée).
  • les paramètres des macros ne sont plus protégés par les chevrons {}
  • la directive MACRO s'utilise après le nom de la macro et non avant
-uz compatibilité UZ80
  • calculs réalisés en entiers 32 bits avec un mauvais arrondi
  • les paramètres des macros ne sont plus protégés par les chevrons {}
  • la directive MACRO s'utilise après le nom de la macro et non avant
Options de développement
-v mode verbeux, affiche des informations et statistiques sur l'assemblage
-d produit des informations lors du pré-processing
-a produit des informations lors de l'assemblage
-n affiche les licences tierces
Format du code source
Généralité
L'assembleur n'est pas du COBOL, il est inutile d'indenter vos sources avec Rasm, autrement que pour faire joli. Il n'est pas nécessaire de séparer un label d'une instruction ou d'un autre label par le caractère deux points, bien qu'il soit possible de le faire. La conséquence directe de cette écriture libre implique une différence avec les assembleurs de conception obsolète. Il n'est pas possible (et heureusement) de créer un label qui ait le même nom qu'une directive ou instruction Z80.

Le défaut de cette liberté est que l'assembleur ne peut pas savoir si vous voulez déclarer un label quand vous vous trompez dans l'écriture du nom d'une macro sans paramètre. Pour palier à ce défaut, vous pouvez ajouter un paramètre fictif “(void)” qui déclenchera une erreur si le nom de macro n'est pas connu.

Les fichiers peuvent être lus au format windows ou unix, une conversion interne et transparente sera réalisée en interne.

Rasm n'est pas sensible à la casse, toutes les lettres sont converties en majuscules en interne. Ne soyez pas surpris de ne voir que des majuscules dans les messages d'erreur.

Un label n'est PAS un alias et n'est PAS une variable, Rasm fait la différence!

- un label fait référence à un emplacement mémoire (une adresse et éventuellement une page mémoire si l'espace de travail correspond à une cartouche ou un snapshot)
- un alias (EQU) est un texte qui, une fois rencontré, est remplacé par un autre, certaines informations étant figées à la définition du texte.
- une variable est globale à l'ensemble du source, sa valeur doit être initialisée et peut-être modifiée à tout moment.
Commentaires
La saisie de commentaire sous Rasm est classique et précédée du caractère point-virgule. Tous les caractères suivants sont ignorés jusqu'au prochain retour chariot.

Note: Il n'y a pas de commentaire multi-lignes
Valeurs littérales
Rasm interprète les valeurs numériques suivantes:
  • En décimal si la valeur commence par un chiffre.
  • En binaire si la valeur commence par un % ou 0b.
  • En octal si la valeur commence par un @.
  • En hexadécimal si la valeur commence par un #, un $, 0x ou se termine par un h.
  • En valeur ascii si un caractère unique est entre quotes.
  • En valeur associée à une variable ou un label, si la littérale commence par une lettre ou un '@' pour les labels locaux.
  • Le symbole $ utilisé seul indique l'adresse de début de l'instruction en cours. Lors d'un define type DEFB, DEFW, DEFI, DEFR ou DEFS, l'adresse courante est celle de l'élément en cours. Un DEF* produira les mêmes données que vous utilisiez plusieurs arguments à la suite ou bien plusieurs DEF*.
Rasm fait tous ses calculs internes en nombre flottant double précision. Un arrondi correct est réalisé en fin de chaine de calcul pour les besoins en nombres entiers.

Attention, le caractère & est réservé pour l'opérateur AND.
Caractères autorisés
Entre quotes, tous les caractères sont autorisés, à vos risques et périls concernant la conversion ASCII vers l'Amstrad. En dehors des quotes, vous pourrez utiliser toutes les lettres, tous les chiffres, le point, l'arobas, les parenthèses, le dollar, les opérateurs plus, moins, multiplié, divisé, le pipe, circonflexe, le pourcent, le dièse, le paragraphe, les chevrons et les deux types de quotes.

Les chaines de caractères entre quotes peuvent contenir des caractères échappés:
  • \t

  • \n

  • \r

  • \f

  • \v

  • \b

  • \0
  • -> sauf avec le PRINT
    Fichiers
    RASM utilise en interne le modèle de fichiers UNIX qu'il converti automatiquement au besoin. En utilisant uniquement des chemins relatifs (et des noms de fichiers que Windows peut comprendre), on peut tout à fait avoir un code qui compile à la fois sous UNIX et Windows sans faire de modification.

    La règle de gestion des chemins relatifs est simple. Tout chemin relatif a pour origine le répertoire du fichier dans lequel il a été lu.
    Labels
    À l'intérieur d'une boucle (REPEAT/WHILE/UNTIL) ou dans une macro, il est possible d'utiliser des labels locaux de la même façon qu'avec l'assembleur intégré de Winape en préfixant le label par le caractère '@'.

    À chaque itération de boucle et ce, pour chaque imbrication de boucle, un suffixe est ajouté au label local contenant la valeur hexadécimale du compteur interne de répétition. Il est ainsi possible d'appeler un label local à une répétition en dehors de la boucle, mais cet usage n'est pas conseillé.

    Il est possible d'utiliser la valeur d'un label dans une commande (ORG par exemple) si et seulement si le label précède la directive.

    Tout label qui commence par le préfixe BRK ou @BRK génère aussi un point d'arrêt.

    En mode DAMS, il est possible d'utiliser la déclaration désuète d'un label en le préfixant d'un point. L'appel à ce label se fera sans le point du début. L'usage des labels de proximité est alors désactivé.

    Labels locaux non exportables
    On peut déclarer un label local à l'intérieur d'une macro ou d'une boucle. Ce label sera invisible hors de son contexte (hors de la macro, ou à chaque répétition de boucle).

    Les labels locaux sont préfixés par le caractère '@'.

    Exemple d'utilisation d'un label local dans une boucle:
    repeat 16
    add hl,bc
    jr nc,@no_overflow
    dec hl
    @no_overflow
    rend
    Labels de proximité
    Hors d'une macro ou d'une boucle, les labels locaux héritent du label global qui précède.

    Exemple d'utilisation d'un label de proximité:
    routine1
    add hl,bc
    jr nc,.no_overflow
    dec hl
    .no_overflow

    routine2
    add hl,bc
    jr nc,.no_overflow
    dec hl
    .no_overflow

    routine3
    xor a
    ld hl,routine1.no_overflow ; récupération du label local à routine1
    ld de,routine2.no_overflow ; idem routine2
    sbc hl,de
    Tags spécifiques aux labels ou structures
    {BANK}
    Le préfixe {BANK} devant un label (exemple: {BANK}monlabel ) permet de récupérer la valeur de la BANK dans laquelle est déclaré le label, plutôt que l'adresse du label.

    Exemple d'utilisation du tag:
    bank 0
    ld a,{bank}maroutine ; sera assemblé LD A,1
    call connect_bank
    jp maroutine
    bank 1
    defb 'coucou'
    maroutine
    jr $
    {PAGE}
    Le préfixe {PAGE} devant un label (exemple: {PAGE}monlabel ) permet de récupérer la valeur type Gate array de la BANK dans laquelle est déclaré le label, plutôt que l'adresse du label. Par exemple pour un label situé dans la BANK 5 la valeur retournée sera #C5

    Si vous utilisez l'adressage mémoire par 64K avec la directive BANKSET, alors la valeur gate array sera déduite du set de 64K ainsi que de l'adresse du label (2 bits de poids fort)

    Exemple d'utilisation du tag:
    buildsna ; force mode snapshot
    Bank 0
    ld a,{page}maroutine ; sera assemblé LD A,#C5
    ld b,#7F
    out (c),a
    jp maroutine
    bank 5
    defb 'coucou'
    maroutine
    jr $
    {PAGESET}
    Le préfixe {PAGESET} devant un label (exemple: {PAGESET}monlabel ) permet de récupérer la valeur type Gate array du BANKSET dans lequel est déclaré le label, plutôt que l'adresse du label. Par exemple pour un label situé dans la BANK 5 la valeur retournée sera #C2

    Exemple d'utilisation du tag:
    bank 0
    ld a,{pageset}maroutine ; sera assemblé LD A,#C2
    ld b,#7F
    out (c),a ; vu qu'on commute toute la RAM le code est supposé être exécuté depuis la ROM dans la majorité des cas
    jp maroutine
    bank 5
    defb 'coucou'
    maroutine
    jr $
    {SIZEOF}
    Le préfixe {SIZEOF} devant un nom de structure ou de sous-structure permet de récupérer la taille de cette dernière.

    Voir la définition des structures ici.
    Coloration syntaxique dans VIM
    • Si vous avez déjà le fichier de coloration syntaxique Z80 il suffit d'ajouter les lignes suivantes au fichier .vim/syntax/z80.vim
    • Ou vous pouvez télécharger le fichier complet de syntaxe ici

    " rasm/winape directives
    syn keyword z80PreProc charset bank write save include incbin incl48 incl49
    syn keyword z80PreProc macro mend switch case break while wend repeat until
    syn keyword z80PreProc buildcpr amsdos lz48 lz49 lzclose protect
    syn keyword z80PreProc direct brk let print stop nolist str
    syn keyword z80PreProc defr dr defi bankset page pageset sizeof endm struct endstruct ends
    syn keyword z80PreProc incexo lzexo lzx7 inczx7 buildsna setcrtc setcpc assert print
    syn keyword z80Reg lix liy hix hiy
    Expressions
    Opérateurs de calcul
    Rasm utilise un moteur d'expression simplifié à priorités multiples (comme le C). Il supporte les opérateurs et fonctions suivant(e)s:
    • * multiplication
    • / division
    • + addition
    • - soustraction
    • & ou AND opérateur logique ET
    • | ou OR opérateur logique OU
    • ^ ou XOR opérateur logique OU exclusif
    • % ou MOD pour faire le modulo
    • && opérateur booléen ET
    • || opérateur booléen OU
    • << multiplication par la puissance n de deux
    • >> division par la puissance n de deux
    • hi() poids fort de l'entier 16 bits
    • lo() poids faible de l'entier 16 bits
    • sin() calcul de sinus
    • cos() calcul de cosinus
    • asin() calcul d'arc-sinus
    • acos() calcul d'arc-cosinus
    • atan() calcul d'arc-tangente
    • int() conversion en nombre entier
    • floor() conversion au nombre entier directement inférieur
    • abs() valeur absolue
    • ln() logarithme népérien
    • log10() logarithme base 10
    • exp() exponentielle
    • sqrt() racine carrée
    • == égalité (ou un seul = en mode Maxam)
    • != ou <> différent de
    • <= inférieur ou égal
    • >= supérieur ou égal
    • < inférieur
    • > supérieur
    Priorité d’exécution des opérateurs
    Plus la prévalence est faible, plus l'opération est prioritaire.
    Opérateurs Prévalence Rasm Prévalence Maxam
    (   ) 0 0
    !   1 464
    *   /   % 2 464
    +   - 3 464
    <<   >> 4 464
    <   <=   ==   =>   >   != 5 664
    &   AND 6 464
    |   OR 7 464
    ^   XOR 8 464
    && 9 6128
    || 10 6128
    Variables
    Variables statiques ou alias
    Il est possible de créer un nombre illimité d’alias avec la directive EQU. Ces alias ne peuvent pas être modifiés une fois qu'ils sont définis.
    Variables dynamiques
    Rasm autorise un nombre illimité de variables pour des calculs internes.

    Syntaxe:
    mavariable=5
    LET mavariable=5 ; syntaxe compatible Winape
    Ces variables peuvent être utilisées comme offset lors d'une boucle de répétition ou comme opérateurs de calcul pour créer des tables de données.

    Exemples:
    dep=0
    repeat 16
    ld (ix+dep),a
    dep=dep+8
    rend
    ang=0
    repeat 256
    defb 127*sin(ang)
    ang=ang+360/256
    rend
    Une directive n'est pas une fonction, c'est un mot clef qui doit être séparé de ses paramètres par au moins un espace.

    Syntaxe correcte: ASSERT (4*mavar)
    Syntaxe incorrecte: ASSERT(4*mavar)
    Directives mémoires
    ALIGN <valeur d'alignement>[,valeur de remplissage]
    Si l'adresse d'écriture du code en cours n'est pas un multiple de la valeur d'alignement, on augmente cette dernière afin que ça soit le cas. Utilisée avec un seul paramètre, cette instruction ne produit pas d'octet sur la sortie. Ainsi, par défaut ce sont des zéros qui seront en mémoire si on réalise un ALIGN entre deux portions de code.

    Utilisée avec le paramètre de remplissage, des octets seront produits (même si la valeur est zéro) et ces données seront comptées dans le calcul d'enregistrement automatique de binaire ainsi que dans le contrôle d'écrasement mémoire.

    Exemple:
    ALIGN 2 ; aligner le code sur une adresse paire
    ALIGN 256 ; aligner le code sur le poids fort de l'adresse
    BANK [numéro de page ROM, numéro de page RAM]
    Sélectionner un emplacement ROM (cartouche) ou RAM (snapshot). L'usage de cette instruction active par défaut l'écriture de la cartouche en fin d'assemblage.

    Les valeurs possibles vont de 0 à 31. En mode snapshot on peut aussi utiliser cette directive, cette fois avec des valeurs de 0 à 35 (64K de base + 512K d'extension mémoire).

    Sans paramètre, la directive ouvre un nouvel espace mémoire de travail
    BANKSET <numéro de bloc de 64K>
    Sélectionner un emplacement mémoire pour les snapshots, en groupant les pages 4 à 4. Le format snapshot v3 supportant au maximum une extension de 512K, il y a 9 sets mémoire indexés de 0 à 8.

    Il est possible d'utiliser BANK et BANKSET en même temps mais il est impératif de ne pas sélectionner la même page à la fois avec BANK et BANKSET. Un contrôle déclenchera une erreur si vous tentez de le faire.

    L'appel de cette directive force automatiquement la génération de snapshot.
    LIMIT <adresse limite>
    Imposer une limite plus basse à l'écriture de l'assemblage. Par défaut, la limite est de 65536 mais on peut avoir besoin de ne pas dépasser une certaine valeur.

    Pour protéger une zone définie, il vaut mieux utiliser la fonction PROTECT.
    ORG <adresse logique>[,adresse d'écriture du code]
    Assembler le code à une adresse spécifique. On peut optionnellement choisir d'assembler le code à une adresse, mais l'écrire à un autre endroit avec le deuxième paramètre.

    Assembler le code à une adresse absolue:
    ORG #8000
    defw $
    ; bytecode produit
    #8000: #00,#80

    Assembler le code à une adresse autre que celle du code:
    ORG #8000,#1000
    defw $
    ; bytecode produit
    #1000: #00,#80

    Retrouver l'adresse physique après l'avoir modifiée:
    ORG #8000,#1000
    defw $ ; cette instruction est logiquement en #8000 mais physiquement écrite en #1000
    ORG $ ; le ORG s'affranchit de l'adresse logique, on est physiquement en #1002 après le defw
    defw $ ; adresse courante est #1002
    ; bytecode produit
    #1000: #00,#80,#02,#10
    PROTECT <adresse de début>,<adresse de fin>
    Empêcher l'écriture de données dans la zone début/fin de l'espace mémoire courant.
    WRITE DIRECT <rom basse>[,<rom haute>[,<RAM>]]
    Cette directive est présente pour compatibilité avec Winape, son usage est déconseillé. Utilisez de préférence les directives BANK ou BANKSET.

    En spécifiant une rom basse (entre 0 et 7) ou une rom haute (entre 0 et 31), cette directive a le même effet que la directive BANK.

    En spécifiant uniquement l'adresse RAM (n'importe quelle valeur) et en désactivant les numéros de rom avec la valeur -1, on créé à chaque appel un nouvel espace mémoire. On peut ainsi assembler plusieurs code au même emplacement mémoire, mais dans un espace différent. Cet usage est équivalent à la directive BANK sans paramètre.
    Directives de définition de données
    CHARSET 'chaine',<valeur> | <code>,<valeur> | <début>,<fin>,<valeur>
    La directive permet de redéfinir des valeurs aux caractères assemblés entre quotes selon quatre formats:
    • 'chaine',<valeur> → Le premier caractère de la chaine aura pour nouvelle valeur la <valeur>. Le caractère suivant <valeur>+1 et ainsi de suite pour tous les caractères de la chaine.
    • <code>,<valeur> → Attribuer au caractère de valeur ASCII <code> la valeur <valeur>.
    • <début>,<fin>,<valeur> → Attribuer aux caractères de valeur ASCII <début> à <fin> une valeur incrémentale en partant de <valeur>.
    • aucun paramètre → réassigne à tous les caractères leur valeur ASCII par défaut.
    Cette fonction est compatible Winape.


    Redéfinir un caractère:
    CHARSET 'T','t' ; les T majuscules seront écrits t minuscules
    defb 'tT'
    ; bytecode produit
    #0000: #74 #74

    Redéfinir quelques caractères non consécutifs:
    CHARSET 'turndiskheo ',0
    defb 'there is no turndisk'
    ; bytecode produit
    #0000: #00,#08,#09,#02,#0B,#05,#06,#0B,#03,#0A,#0B,#00,#01,#02,#03,#04,#05,#06,#07

    Redéfinir des caractères consécutifs:
    CHARSET 'A','Z','a' ; transformer toutes les majuscules en minuscules
    defb 'abcdeABCDE'
    ; bytecode produit
    #0000: #61,#62,#63,#64,#65,#61,#62,#63,#64,#65
    DB, DEFB, DM, DEFM <valeur>[,<valeur>,...]
    Cette directive prend un ou plusieurs paramètres et génère une suite d'octets représentative des paramètres en entrée. La valeur peut être une valeur litérale, une formule dont le résultat sera éventuellement arrondi et tronqué ou même une chaine de caractères dont chaque caractère produira un octet en sortie égale à sa valeur ASCII, sauf si la directive CHARSET a été utilisée pour redéfinir ces valeurs.

    Exemple:
    defb 'r'-'a'+'A',oudoudou',#FF,lo($)
    La référence d'adresse courante est celle de l'octet en cours par défaut.
    DEFW, DW <valeur>[,<valeur>,...]
    Cette directive prend un ou plusieurs paramètres et génère une suite de mots (deux octets) représentative des paramètres en entrée. Les valeurs peuvent être une valeur littérale, une formule dont le résultat sera éventuellement arrondi et tronqué. Cette directive ne supporte pas une chaine de plusieurs caractères comme valeur.

    Exemple:
    defw mylabel1,mylabel2,'a'+#100

    DEFI
    Cette direction prend un ou plusieurs paramètres et génère une suite de double-mots (4 octets) représentative des paramètres en entrée. Les valeurs peuvent être une valeur littérale, une formule dont le résultat sera éventuellement arrondi et tronqué. Cette directive ne supporte pas une chaine de plusieurs caractères comme valeur.
    DEFR, DR <nombre réel>[,<nombre réel>,...]
    Cette directive prend un ou plusieurs paramètres et génère une suite de nombre réels (5 octets chaque) compatibles avec le firmware des Amstrad CPC.

    Exemple:
    defr 5/12,7/3
    DEFS, DS <répétition>[,<valeur>,[<répétition>,...]
    Cette directive génère une suite d'octets répétitive. Si la valeur de remplissage est omise alors zéro sera pris par défaut. Si la valeur de répétition est nulle alors aucun octet ne sera produit. Il est possible de déclarer plusieurs suites de répétition avec le même DEFS mais les premières répétitions sera toujours interprétées comme ayant une valeur à répéter.

    Exemple:
    defs 5,8,4,1 ; output=#08,#08,#08,#08,#08,#01,#01,#01,#01
    defs 5,8,4 ; output=#08,#08,#08,#08,#08,#00,#00,#00,#00
    defs 5 ; output=#00,#00,#00,#00,#00
    <alias> EQU <chaine de remplacement>
    Création d'un alias. Quand l'assembleur rencontrera l'alias dans une expression, le texte sera remplacé par celui défini lors du EQU. Un test de récursivité infini est réalisé à la création de l'alias.

    Exemple:
    tab1 EQU #8000
    tab2 EQU tab1+#100

    ld hl,tab2
    STR 'chaine1'[,'chaine2'...]
    Directive similaire à DEFB, sauf que le dernier caractère de chaque chaine aura son bit 7 forcé à 1 (opération OR #80 sur le dernier octet).

    Les deux lignes suivantes produiront les mêmes octets:
    defb 'roudoudo','u'+128
    str 'roudoudou'
    STRUCT <nom de prototype>[,<nom de variable>]
    Le Z80 est particulièrement apte à traiter des structures de données grâce aux instructions indexées (registres IX et IY) mais on peut simplement vouloir déclarer des structures par convenance personnelle.

    Exemple de création d’une structure
    struct st1
    ch1 defw 0
    ch2 defb 0
    endstruct
    La structure st1 est créée avec deux champs ch1 et ch2. Aucun octet n’est produit en mémoire.
    Imbriquer les structures
    struct metast1
    struct st1 pr1
    struct st1 pr2
    endstruct
    La structure metast1 est créée avec deux sous-structures de type st1 appellées pr1 et pr2

    Pour récupérer la taille d’une structure, il est recommandé d’utiliser le préfixe {SIZEOF}. La taille d’une structure peut être récupérée avec le nom de son prototype comme Vasm mais cette pratique est fortement déconseillée et n’existe qu’à des fins de compatibilité.
    LD HL,{SIZEOF}metast1
    LD HL,metast1

    La directive STRUCT appelée avec deux paramètres va créer en mémoire une structure sur la base d’un prototype existant, qu’il faudra nommer. Par exemple ci-dessous, on va créer une structure mymeta de type metast1.

    struct metast1 mymeta

    On peut récupérer les offsets des champs d’une structure en utilisant les informations du prototype:
    LD A,(IX+metast1.pr2.ch1) ; offset car prototype utilisé

    Si on utilise le nom d’une structure statique alors c’est l’adresse absolue qui est renvoyée:
    LD HL,mymeta.pr2.ch1
    LD A,(HL)
    Directives d'import et de compression
    INCLUDE, READ 'fichier à lire'
    Lire un fichier texte et l'intégrer au code source à l'emplacement de l'instruction de lecture. Le chemin relatif de lecture a pour racine l'emplacement du fichier dans lequel est l'instruction de lecture. Un chemin absolu s'affranchit de ce répertoire racine.

    Il n'y a pas de limite de récursivité en lecture. Attention à ce que vous faites.
    INCBIN 'fichier à lire'[,offset[,size[,offset étendu[,OFF]]]] ou INCBIN 'fichier wav',SMP|SM2|SM4|DMA
    Lire un fichier binaire. Les données lues seront directement injectées. Les paramètres optionnels sont compatibles avec la fonction INCBIN de Winape. L'offset n'est pas limité à 64Ko comme Winape. L'offset étendu est là pour compatibilité. Son usage est à éviter pour rester lisible.

    Il est possible de donner un offset négatif, relatif à la fin du fichier.

    Il est possible de donner une taille de fichier négative. La taille lue sera égale à la taille totale du fichier ajoutée à cette valeur négative. Pour tout lire sauf les 10 derniers octets, on précisera une taille de -10 dans la commande.

    Une taille de zéro chargera tout le fichier.

    Paramètre OFF: Si on souhaite charger un fichier pour initialiser de la “mémoire” et qu'on souhaite assembler du code par dessus, on peut désactiver pour la lecture de ce fichier le contrôle d'écrasement.

    Exemple:
    org #4000
    incbin'makeraw.bin',0,0,0,OFF ; lecture en #4000 avec contrôle d'écrasement désactivé
    org #4001
    defb #BB ; écrasement du deuxième octet sans erreur
    Exemple de lecture de fichier audio:
    org #4000
    incbin'sound.wav',DMA
    Les fichiers WAV sont à priori tous supportés quel que soit leur format, mono-canal ou multi-canal. Une fusion des voix sera réalisée en cas de fichier multi-canal. La fréquence d'échantillonage n'est pas prise en compte. Chaque échantillon sera converti en une valeur PSG. Vos fichiers audio pour liste DMA devront au préalable avoir été converti à 15600Hz. Pour les samples classiques, à votre vitesse de relecture. Il existe deux formats additionnels pour les samples classiques nommés SM2 et SM4.

    Le format SM2 contient deux valeurs sur un seul octet, premier échantillon dans les bits de poids fort.

    Le format SM4 contient quatre valeurs sur un seul octet, premier échantillon dans les bits de poids fort. Le système retenu est le suivant. Les valeurs codées sont les valeurs 0,13,14,15. Ainsi on peut coder sur seulement 2 bits avec toute l'amplitude 4 bits du PSG. Il suffit de copier les deux bits en position 2 et 3. Le zéro reste zéro de facto.

    INCL48, INCL49, INCLZ4, INCZX7, INCEXO 'fichier à lire'
    Lire un fichier binaire, le compresser en LZ48, LZ49, LZ4, Exomizer ou ZX7 et l'injecter directement dans le code.
    LZ48, LZ49, LZ4, LZX7, LZEXO
    Ouvrir un segment de code compressé en LZ48,LZ49, LZ4, ZX7 ou Exomizer. Le code produit sera compressé après assemblage et l'ensemble du code situé après la zone sera relogé.

    Il n'est pas possible d'appeler un label situé après un segment compressé depuis le code compressé pour des raisons évidentes dûes aux aléas de la compression. Une erreur s'affichera expliquant pourquoi.

    Limitations:
    • Le code ou les données d'une zone LZ ne peut excéder l'espace d'adressage de 64Ko.
    • Il n'est pas possible d'imbriquer les segments compressés.

    Exemple:
    org #1000
    ld hl,zecrunch
    ld de,#8000
    call decrunch
    call #8000
    jp next ; label next after crunched zone will be relocated

    zecrunch
    lz48 ; this section will be crunched
    org #8000,$
    nop
    nop
    nop
    ret
    lzclose

    next
    ret
    LZCLOSE
    Fermer une zone LZ.
    Directives de code conditionnel
    ASSERT <condition>[,texte,texte,texte,...]
    Vérifier une condition et arrêter l'assemblage si la condition est fausse.

    Exemple:
    assert mygenend-mygenstart<#100
    assert mygenend-mygenstart<#100,'code trop gros'
    IF <condition>, IFNOT <condition>, ELSE, ELSEIF <condition>, ENDIF
    Directive de test et définition de blocs pour le code conditionnel.

    Exemple:
    CODE_PRODUCTION=1
    [...]
    if CODE_PRODUCTION
    or #80
    else
    print 'version de test'
    endif
    IFDEF, IFNDEF <variable ou label>
    Ces deux directives permettent de tester l'existence ou la non existence d'une variable ou d'un label, AVANT la directive.
    IFUSED, IFNUSED <variable ou label>
    Ces deux directives permettent de tester l'utilisation ou la non utilisation d'une variable ou d'un label, AVANT la directive.
    MACRO
    Rasm supporte les macros avec chevrons (compatible avec Winape). Il est possible de faire de l'assemblage conditionnel avec les macros car à chaque appel de macro, le code d'origine est inséré, les paramètres substitués et enfin le code est interprété de façon classique.

    Exemple pour une écriture longue distance générique (sauf pour B ou C):
    macro LDIXREG registre,dep ; chaque paramètre séparé par une virgule
    if {dep}<-128 || {dep}>127
    push bc
    ld bc,{dep}
    add ix,bc
    ld (ix+0),{registre}
    pop bc
    else
    ld (ix+{dep}),{registre}
    endif
    mend
    Note: Le marqueur de fin de macro peut être indifférement MEND ou ENDM


    Macros sans paramètre
    En cas de faute de frappe, pour éviter que la macro mal orthographiée soit remplacée par un label, il est conseillé d'utiliser le paramètre (VOID) à chaque appel. Ainsi, si la macro est mal orthographiée, la présence du (VOID) déclenchera une erreur.

    macro sansparam
    nop
    mend

    sansparam (void) ; appel sécurisé de la macro


    Appel de macro en paramètre statique ou dynamique
    Les macros de Rasm sont (en logique interne) du code qui est remplacé au vol lors de l'assemblage. Il y a deux possibilités de remplacement pour les paramètres. Soit le paramètre est copié tel que, soit il peut être calculé et c'est sa valeur calculée qui sera injecté dans la macro.

    macro test myarg
    defb {myarg}
    mend

    repeat 2
    test repeat_counter
    rend
    repeat 2
    test {eval}repeat_counter
    rend
    Dans la première boucle, c'est la ligne defb repeat_counter qui sera développée tandis que le second appel, avec le paramètre précédé du tag {eval}, c'est la première valeur de repeat_counter qui sera développée, entrainant deux defb identiques.
    PRINT 'chaine',<variable>,<expression>
    Écrire du texte, variables ou expressions lors de l'assemblage. Concernant les valeurs numériques l'affichage par défaut est un nombre flottant mais il est possible de formater les variables en préfixant la variable par des tags:

    {hex}
    afficher la variable en hexadécimal. Si la variable vaut moins de #FF alors l'affichage sera forcé sur deux chiffres. Si la variable vaut moins de #FFFF alors l'affichage sera forcé sur quatre chiffres. Au dessus il n'y aura pas d'extra-zéros.
    {hex2}, {hex4}, {hex8}
    pour forcer l'affichage quel que soit la valeur, sur 2, 4 ou 8 chiffres.
    {bin}
    afficher la variable en binaire. Si la variabke vaut moins de #FF alors l'affichage sera forcé sur 8 bits. Si la variable vaut moins de #FFFF alors l'affichage sera forcé sur 16 bits. Un pré-traitement enlève les 16 bits supérieurs de la valeur 32 bits au cas où tous les bits sont à 1 (nombre négatif).
    {bin8},{bin16},{bin32}
    pour forcer l'affichage quel que soit la valeur, sur 8, 16 ou 32 bits.
    {int}
    afficher en décimal, nombre entier.
    FAIL 'chaine',<variable>,<expression>
    Directive dérivée de PRINT, qui sort de Rasm en erreur.
    REPEAT <nombre de répétition>[,variable], REND / REPEAT, UNTIL <condition>
    Répète un bloc d'instructions. On peut soit fixer un nombre de répétitions, soit utiliser le mode conditionnel avec la directive de fin de bloc UNTIL. Il est possible à tout moment de consulter le numéro d'itération du repeat courant avec la variable REPEAT_COUNTER. Pour le cas de répétition non conditionnel, on peut donner un nom de variable (qui existe déjà ou non) pour que le compteur y soit recopié à chaque itération.

    Exemple:
    repeat 10
    ldi
    print repeat_counter
    rend

    cpt=10
    repeat
    ldi
    cpt=cpt-1
    until cpt>0
    Exemple avec compteur exporté:
    repeat 10,hello
    ldi
    print hello
    rend

    Note: La variable 'hello' peut exister ou non. Si elle n'existe pas au début du REPEAT, elle sera crée.
    STOP
    Arrêter l'assemblage. Aucun fichier ne sera écrit.
    SWITCH, CASE, BREAK, DEFAULT, ENDSWITCH
    La syntaxe est une mimic du case en C, avec la particularité de pouvoir écrire plusieurs CASE qui ont la même valeur, ce qui donne plus de souplesse au code conditionnel.

    Dans cet exemple, l'appel de la macro avec 5 assemblera toutes les chaines de defb avec 'oui' ou 'encore oui':
    macro ouioui mavar
    switch {mavar}
    nop ; pas assemblé car hors case
    case 3
    defb 'non'
    case 5
    defb 'oui'
    case 7
    defb 'encore oui'
    break
    case 8
    defb 'non'
    case 5
    defb 'encore oui'
    break
    default
    defb 'non'
    endswitch
    mend
    WHILE, WEND
    Répète un bloc d'instructions tant que la condition est vérifiée. Il est possible de consulter à tout moment la variable WHILE_COUNTER pour déclencher des évènements en fonction du numéro d'itération.

    Exemple:
    cpt=10
    while cpt>0
    ldi
    cpt=cpt-1
    print 'cpt=',cpt,' while_counter=',while_counter
    wend
    La boucle sera exécutée 10 fois de suite produisant la sortie texte suivante:
    Pre-processing [while.asm]
    Assembling
    cpt= 9.00 while_counter= 1.00
    cpt= 8.00 while_counter= 2.00
    cpt= 7.00 while_counter= 3.00
    cpt= 6.00 while_counter= 4.00
    cpt= 5.00 while_counter= 5.00
    cpt= 4.00 while_counter= 6.00
    cpt= 3.00 while_counter= 7.00
    cpt= 2.00 while_counter= 8.00
    cpt= 1.00 while_counter= 9.00
    cpt= 0.00 while_counter= 10.00
    Write binary file rasmoutput.bin (20 bytes)
    Directives de sortie fichier
    AMSDOS
    Ajoute un entête Amsdos au fichier binaire produit automatiquement par Rasm. Cet entête n'est pas ajouté lors d'un SAVE. La fonction SAVE dispose elle aussi d’une option pour ajouter cet entête à la demande.
    BREAKPOINT [<adresse>]
    Ajoute un point d'arrêt (ce n'est pas une instruction qui est assemblée) avec pour adresse de break l'adresse de l'instruction suivante ou celle du paramètre optionnel. Les points d'arrêt peuvent être exportés sous forme de fichier brut ou dans les snapshots (compatible avec les émulateurs ACE et Winape).

    Note: Tout label qui commence par le préfixe BRK ou @BRK génère à la fois un label et un point d'arrêt.

    BUILDCPR
    La directive n'a plus d'utilité. Elle était supposée forcer l'écriture d'une cartouche lorsqu'on cumulait les différents types de sauvegarde.
    BUILDSNA [V2]
    L'usage de la directive BUILDSNA indique à Rasm qu'on veut générer un snapshot et non une cartouche (dans le doute c'est une cartouche qui est générée).

    Par défaut le snapshot est initialisé avec un 6128 CRTC 0 mais il est possible avec les directives SETCRTC et SETCPC de choisir un autre type de CPC et de CRTC.

    Le snapshot généré par Rasm inclu un écran de taille classique (le même que sous Basic), les encres sont aux valeurs par défaut du Basic (non clignottantes). Les 3 voies audio sont désactivées, les roms désactivées et le mode d'interruption est 1.

    Exemple:
    buildsna ; il est conseillé de commencer par déclarer le SNA pour
    ; éviter d'avoir un problème de limite à 512K

    bankset 0 ; assembler dans les premiers 64K de la machine
    org #1000
    run #1000 ; le snapshot s'exécutera en #1000

    ld b,#7F
    ld a,{page}mydata ; récupère l'ordre gate array de pagination mémoire
    out (c),c
    ld a,(mydata)
    jr $

    bank 6 ; choisir la troisième bank du deuxième jeu de 64K
    nop
    mydata defb #DD

    bank ; sans paramètre, créer un espace mémoire indépendant qui ne
    ; sera pas enregistré dans le snapshot

    pouet
    repeat 10
    cpi
    rend
    camion
    save"autrechose",pouet,camion-pouet

    Option de compatibilité pour la création de snapshot version 2: Certains émulateurs ou cartes hardware ne gèrent pas encore le format v3. Pour rétrograder les snapshots en format v2 (128K maximum, non compressés), il suffit d'ajouter le paramètre V2 après la directive comme suit:
    buildsna v2
    RUN <adresse>[,<gate array configuration>]
    Cette directive n'est prise en compte que si on génère un snapshot. Alors l'adresse de démarrage du code sera injectée dans le snapshot. En option on peut spécifier la configuration du gate array, typiquement pour exécuter un programme depuis les 64K de mémoire étendue.
    SAVE 'nom de fichier',<adresse>,<taille>[,AMSDOS|DSK[,'fichier dsk'[,<face>]]]
    Enregistre un fichier binaire à partir de la mémoire adresse jusqu'à adresse+taille de l'espace mémoire en cours. Bien que l'instruction SAVE puisse être déclarée à n'importe quel moment, les enregistrements de fichier sont toujours réalisés en fin d'assemblage si et seulement si il n'y a pas eu d'erreur. Il n'est donc pas possible d'enregistrer des états intermédiaires d'assemblage.

    Lorsqu'on enregistre sur une image de disquette (DSK), le nom du fichier binaire est automatiquement tronqué et mis en majuscule si il n'est pas conforme aux limitations de l'AMSDOS.

    Exemples:
    SAVE 'monfichier.bin',debut,taille ; Enregistrer un fichier binaire brut
    SAVE 'monfichier.bin',debut,taille,AMSDOS ; Enregistrer un fichier binaire avec entête AMSDOS
    SAVE 'monfic.bin',debut,taille,DSK,'fichierdsk.dsk' ; Enregistrer un fichier binaire sur une image de disquette
    SETCPC <modèle>
    Choisir le modèle de CPC quand on enregistre un snapshot. Les valeurs autorisées sont:
    • 0 : CPC 464
    • 1 : CPC 664
    • 2 : CPC 6128
    • 4 : 464 Plus
    • 5 : 6128 Plus
    • 6 : GX-4000
    SETCRTC <modèle>
    Choisir le modèle de CRTC quand on enregistre un snapshot. Les valeurs autorisées vont de 0 à 4. Pour rappel, les CPC ont des CRTC 0,1,2 ou 4 et les Plus ou GX-4000 ont tous le CRTC 3.
    Directives de compatibilité
    LIST, NOLIST, LET
    Directives ignorées, pour compatibilité avec Winape.
    Jeu d'instruction
    Toutes les instructions documentées et non documentées sont supportées.

    L'adressage 8 bits des registres d'index IX et IY se fait indifféremment avec LX, IXL ou XL, etc.

    Les instructions complexes s'écrivent de la façon suivante:
    res 0,(ix+0),a
    bit 0,(ix+0),a
    sll 0,(ix+0),a
    rl 0,(ix+0),a
    rr 0,(ix+0),a

    Syntaxes des instructions non documentées:
    out (#12),a ; #12 peut être n'importe quelle valeur 8 bits
    in a,(#12)
    in 0,(c) ou in f,(c)
    sll <registre> ou sl1 <registre>

    Syntaxes spéciales autorisées:
    - PUSH multi-arguments
    push bc,de,hl ; → push bc : push de : push hl
    - NOP répétitif
    nop 4 ; → nop : nop : nop : nop
    - complex LD
    LD BC,BC ; → LD B,B : LD C,C
    LD BC,DE ; → LD B,D : LD C,E
    LD BC,HL ; → LD B,H : LD C,L
    LD DE,BC ; → LD D,B : LD E,C
    LD DE,DE ; → LD D,D : LD E,E
    LD DE,HL ; → LD D,H : LD E,L
    LD HL,BC ; → LD H,B : LD L,C
    LD HL,DE ; → LD H,D : LD L,E
    LD HL,HL ; → LD H,H : LD L,L

    LD HL,(IX+n) ; → LD H,(IX+n+1) : LD L,(IX+n)
    LD HL,(IY+n) ; → LD H,(IY+n+1) : LD L,(IY+n)
    LD DE,(IX+n) ; → LD D,(IX+n+1) : LD E,(IX+n)
    LD DE,(IY+n) ; → LD D,(IY+n+1) : LD E,(IY+n)
    LD BC,(IX+n) ; → LD B,(IX+n+1) : LD C,(IX+n)
    LD BC,(IY+n) ; → LD B,(IY+n+1) : LD C,(IY+n)

    LD (IX+n),HL ; → LD (IX+n+1),H : LD (IX+n),L
    LD (IY+n),HL ; → LD (IY+n+1),H : LD (IY+n),L
    LD (IX+n),DE ; → LD (IX+n+1),D : LD (IX+n),E
    LD (IY+n),DE ; → LD (IY+n+1),D : LD (IY+n),E
    LD (IX+n),BC ; → LD (IX+n+1),B : LD (IX+n),C
    LD (IY+n),BC ; → LD (IY+n+1),B : LD (IY+n),C
    Limitations
    Ce logiciel et sa documentation utilisent la licence MIT "expat"

    « Copyright © BERGÉ Édouard (roudoudou)

    Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation/source files of RASM, to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

    The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. The Software is provided "as is", without warranty of any kind, express or implied, including but not limited to the warranties of merchantability, fitness for a particular purpose and noninfringement. In no event shall the authors or copyright holders be liable for any claim, damages or other liability, whether in an action of contract, tort or otherwise, arising from, out of or in connection with the software or the use or other dealings in the Software. »