Etendre Xassembler avec des directives
publication: 4 avril 2021 / mis à jour 8 avril 2021
Les directives d'assemblage
Reprenons le code assembleur PLUS.ASM:
.include "m328pdef.inc" .include "macros.inc" .cseg .org 0x00 PLUS: ld t0, Y+ ld t1, Y+ add tosl, t0 adc tosh, t1 ret
Si on prend la ligne de code ld t0, Y+, on voit l'opérande t0
qui n'est pas défini dans Xassembler. Idem pour t1
t0 et t1 sont définis en assembleur dans le fichier macros.inc. Extrait:
.def t0 = r16 .def t1 = r17
Pour notre premier essai de méta assemblage, nous avons défini t0 et t1
avec constant comme suit en langage FORTH:
r16 constant t0 r17 constant t1 r24 constant tosl r25 constant tosh : plus [ t0 Y+ ld, ] [ t1 Y+ ld, ] [ tosl t0 add, ] [ tosh t1 adc, ] [ ret, ] ;
Définir t0 t1 sous forme de constantes est acceptable pour un petit exemple, mais non valide pour un gros programme.
Sous gForth, si on définit la même constante plus d'une fois, on va se retrouver avec des valeurs incontrôlables dans le code à méta assembler.
L'idée la plus élégante serait de créer des mots .def .equ .set, ayant les
mêmes propriétés que leur équivalent assembleur, même si la sytaxe est un peu différente. Exemple:
.def t0 = r16
devient en FORTH:
r16 .def t0
La directive .def
La directive .def définit un synonyme pour un registre. Voici
comment est défini .def dans Xassembler.txt:
\ Defines a synonym for a register, syntax: \ R16 .def MyReg : .def ( comp: n --| exec: -- n) value ;
Exemple de code source en assembleur:
; Register definitions .def upl = r2 ; not in interrupt .def uph = r3 ; not in interrupt .def r_zero = r5 ; read only zero .def r_one = r6 ; read only one .def r_two = r7 ; read only two .def t8 = r8 ; Not in interrupt .def wflags = r9 ; not in interrupt
réécrit en FORTH:
\ Register definitions r2 .def upl \ not in interrupt r3 .def uph \ not in interrupt r5 .def r_zero \ read only zero r6 .def r_one \ read only one r7 .def r_two \ read only two r8 .def t8 \ Not in interrupt r9 .def wflags \ not in interrupt
La directive .equ
La directive .equ définit un symbole en lui affectant une valeur.
La valeur peut être modifiée ultérieurement. Voici
comment est défini .equ dans Xassembler.txt:
\ Defines a symbol and sets its value \ later changes of this value remain possible, syntax: \ 1234 .equ test : .equ ( comp: n --| exec: -- n) >in @ >r bl word count 2dup find-name \ leave nfa or 0 ?dup if \ word defined r> drop name>int \ nfa > cfa 16 + >r \ cfa > pfa 2drop r> ! \ store value else \ word undefined drop r> >in ! drop value then ;
Exemple de code source en assembleur:
; ***** DATA MEMORY DECLARATIONS ***************************************** .equ FLASHEND = 0x3fff ; Note: Word address .equ IOEND = 0x00ff .equ SRAM_START = 0x0100 .equ SRAM_SIZE = 2048 .equ RAMEND = 0x08ff .equ XRAMEND = 0x0000 .equ E2END = 0x03ff .equ EEPROMEND = 0x03ff .equ EEADRBITS = 10
réécrit en FORTH:
\ ***** DATA MEMORY DECLARATIONS ***************************************** $3fff .equ FLASHEND \ Note: Word address $00ff .equ IOEND $0100 .equ SRAM_START 2048 .equ SRAM_SIZE $08ff .equ RAMEND $0000 .equ XRAMEND $03ff .equ E2END $03ff .equ EEPROMEND 10 .equ EEADRBITS
Notre mot .equ teste si le symbole existe déjà. Si le symbole n'existe
pas, il crée ce symbole en lui affectant la valeur souhaitée. Si le symbole a déjà
été défini, il en modifie simplement sa valeur.
La directive .set
Cette directive .set fixe la valeur d'un symbole. Cette valeur ne peut
pas être modifiée. Pas d'exemple.
