Vocabulaire Xassembler pour Atmega

publication: 27 mars 2021 / mis à jour 27 mars 2021

Read this page in english

 

Pour générer un code utilisable sur une carte ARDUINO, il faut préalablement compiler et assembler des primitives dans la zone TARGET. Pour ce faire, il est nécessaire de disposer, sous gForth, d'un assembleur spécifique.

Assembleur pour Atmega

gForth dispose d'un certain nombre de vocabulaires, dont un vocabulaire ASSEMBLER.

Pour voir la liste de tous les vocabulaires de gForth, il faut exécuter VOCS:

vocs
libcc-types assembler esc-sequences new-locals-wl locals-types 
locals environment-wordlist Root Forth  ok

Les vocabulaires disponibles sont affichés après vocs. On y voit le vocabulaire assembler.

Sélection d'un vocabulaire

Pour voir le contenu d'un vocabulaire, il suffit de taper le nom de ce vocabulaire, suivi de words:

assembler words 
makeflag YET BUT ?DO REPEAT AGAIN UNTIL WHILE DO BEGIN ELSE AHEAD 
THEN IF >offset ~cond PREFETCHT2 PREFETCHT1 PREFETCHT0 PREFETCHNTA 
SFENCE PSWABD PFPNACC PFNACC PF2IW PI2FW PSHUFW PSADBW PMULHUW 
PMOVMSKB PMINUB PMINSW PMAXUB PMAXSW PINSRW PEXTRW PAVGW PAVGB 
....[CUT]...
[BP+DI] [BP+SI] [BX+DI] [BX+SI] wadr wadr: bregs breg Regs finish0F 
0F, finishb finish opcode, rbytes, bytes, .qa .q .da .d .wa .w .b 
sclear pre- .arel .64bit .rex .64now .64size .onow .osize .anow 
.asize seg byte? Adisp? Aimm? imm# imm disp# disp SIB# SIB ModR/M# 
ModR/M +rel c! allot here , >exec nonrelocate nrc (+rel >codes 
case? user' [A] [F]  ok

L'ennui est que le contenu de ce vocabulaire assembler ne convient pas du tout pour la génération de code destiné au processeur Atmega équipant les cartes ARDUINO.

Comme il est hors de question de supprimer ce vocabulaire assembler et le remplacer par notre vocabulaire assembler compatible Atmega, on va définir un vocabulaire Xassembler.

Création du vocabulaire Xassembler

Pour créer ce nouveau vocabulaire, on va utiliser le mot vocabulary:

vocabulary Xassembler 

Afin de vérifier si ce nouveau vocabulaire a bien été intégré, exécutons vocs:

vocs
Xassembler libcc-types assembler esc-sequences new-locals-wl locals-types 
locals environment-wordlist Root Forth  ok

On vérifie l'ordre de recherche des mots en tapant order:

order
Forth Forth Root     Forth  ok

Maintenant, il faut indiquer à gForth que toutes les nouvelles définitions doivent être intégrées à ce vocabulaire en exécutant definitions:

Xassembler definitions 

On vérifie à nouveau l'ordre de recherche des mots avec order:

order
Xassembler Forth Root     Xassembler  ok

L'ordre de recherche est lu de gauche à droite. Tout nouveau mot sera défini dans Xassembler. Si par hasard on crée dans ce vocabulaire Xassembler un mot déjà défini dans le vocabulaire FORTH, ce mot sera créé dans ce vocabulaire sans altérer son homonyme dans le vocabulaire FORTH.

Dans l'article intitulé Convertisseur de notation infixée vers notation postfixée on crée un vocabulaire algebra, dans mequel on définit des homonymes pour * / + -, etc... Dans le contexte de ce vocabulaire algebra, par exemple le mot + fonctionnera de manière différente du mot + défini dans le vocabulaire FORTH.

Structuration des fichiers source

Voici la manière dont les fichiers sources peuvent s'organiser:

----------/ <meta>
          |     meta.txt
          |     meta_AVR328.txt
          |     kernel.txt
          |---------------------/ <avr>
                                /     Xassembler.txt
                                /     m328def.txt
                                /     core.txt
                                /
                                / <pic>
                                /     Xassembler.txt         
                                /     core.txt

On a d'abord un répertoire meta dans lequel on va retrouver:

Exemple de contenu du fichier meta_avr328.txt compilé par gForth:

include meta.txt
include avr/m328def.txt
include avr/Xassembler.txt
include avr/core.txt
include kernel.txt     

Des mots comme , c, sont redéfinis dans meta.txt pour permettre la génération de code dans TARGET:

Si on souhaite générer un noyau FORTH pour un autre processeur, il suffit d'écrire un fichier meta_PIC.txt par exemple, contenant:

include meta.txt
include pic/Xassembler.txt
include pic/core.txt
include kernel.txt     

Le contenu du fichier pic/Xassembler.txt sera très différent de celui du fichier avr/Xassembler.txt.

Contenu du fichier Xassembler.txt pour Atmega

Pas question de réécrire un assembleur. Autant reprendre celui qui existe déjà dans FlashForth: FlashForth assembler for Atmega chips

Afin de rendre compatible le contenu de ce fichier avec gForth, on modifie très légèrement son contenu en mettant en début de fichier:

\ define Xassembler  
vocabulary Xassembler 
Xassembler definitions 
 
: i, 
    , ; 
: flash 
    ; 
: ram 
    ; 
 
\ OFLASH  constant pfl 
\ RAMPZV  constant zfl     \ value [0..3]     

Le reste du code source n'est pas modifié, à l'exception de if, qui été provisoirement neutralisé dans l'attente d'une mise au point.

L'idée finale est de remplacer ce code assembleur:

PLUS_L:
.db     NFA|INLINE4|1, "+"
 
PLUS:
        ld      t0, Y+        
        ld      t1, Y+
        add     tosl, t0
        adc     tosh, t1
        ret

par ceci dans nos primitives:

code + 
   y+ t0 ld, 
   y+ t1 ld, 
   t0 tosl add, 
   t1 tosh adc, 
   ret, 
end-code 

Il nous faudra donc définir les mots code et end-code dans le vocabulaire meta. C'est ce que nous verrons dans un autre article...