Retro-computing et MSX


Le retro computing ?

  • Ne me dites pas que vous n'avez jamais entendu parler du retro-computing!
    • Il s'agit de la madeleine de Proust pour les gens qui ont passé leur belle jeunesse sur des micro-ordinateurs tels que MSX, Commodore, Atari, Amstrad...
  • Il y a des tas de moyen de s'amuser avec ces vieilleries, notamment par le biais des émulateurs.
  • Ces micros font certe pâle figure de nos jours, mais ils sont relativement faciles à programmer, grâce à la doc abondante que l'on trouve sur internet.
    • Ils peuvent donc faire office de récréation mentale bien plus stimulante qu'un bête sudoku, entre deux développements fatigants.
    • On peut également pratiquer cette discipline simplement pour s'amuser. Mais faire les choses pour s'amuser est assez mal vu de nos jours. Je vous laisserai donc le choix de chercher d'autres justifications rationnelles.



Le MSX

Pourquoi le MSX ?
  • Pourquoi programmer un MSX plutôt qu'un micro 32 bits de l'époque ?
    • Tout simplement parce que le MSX est relativement simple avec son Z80 (8 bits). Avec un peu d'expérience de la programmation et des architectures, vous pouvez espérer avoir des résultats intéressants en moins d'une semaine. Si vos vacances sont plus longues, vous vous amuserez donc encore plus.
    • Les micros 32 bits (68000 par exemple) sont plus puissants, mais nécessitent plus de connaissances et sortent un peu du cadre fixé par ce billet (s'amuser avec des choses simples).
    • D'autre part, le challenge est très présent. Avec un Z80 à 3,58Mhz, chaque cycle compte!


Très bref historique du MSX
  • Je vais vous présenter succintement le MSX.
    • Vous trouverez tout un tas d'articles sur le net, ainsi que des forums spécialisés, y compris en français.


  • En deux mots, le MSX a été une tentative de standardisation de la micro-informatique par les japonais (société Ascii Corporation), associés pour l'occasion avec Microsoft (pour le basic).
  • La norme MSX fut déclinée en plusieurs vagues:
    • le MSX (appellé plus tard MSX 1)
    • le MSX 2.
    • En France, ça s'arrête là avec l'abandon de la commercialisation des modèles. Mais il y eu encore le MSX 2+, puis le MSX TurboR.
  • Tous les MSX furent basés sur un socle technique commun (pour la standardisation).
  • Ils furent vendus par d'innombrables marques (Sanyo, Philips, Sony, Canon, pour ne citer que les plus connues). Le microprocesseur était un Z80 pour toute la gamme. Seuls les MSX Turbo-R embarquaient un Z80 et un R800 (le R800 était un Z80 amélioré 16 bits, fonctionnant à 7 Mhz).
  • Au sein de la norme, il y eu quelques évolutions, notamment musicales: certaines cartouches de jeux étaient proposées avec un circuit sonore monté sur la cartouche (le SCC). Le SCC étendait les capacités sonores du MSX à 8 voies. D'autres extensions proposaient de la synthèse FM à un prix plutot concurrentiel pour l'époque (cartouche FM PAC).


  • Le MSX a péri face aux Amiga et autres Atari ST, supérieurs techniquement.
  • De cette période faste, il nous reste de beaux souvenirs, et la possibilité de retrouver les programmes de l'époque grâce aux émulateurs.
  • Il reste également quelques juteuses franchises, telles que Metal Gear ou Castlevania, qui ont débuté sur MSX.


Au fait, que signifie MSX ?
  • Microsoft SuXx ?


Pour en savoir plus




Mise en place des outils de développement


La base

  • Nous allons utiliser les outils modernes mis à notre disposition, avec Linux en tant qu' OS hôte.
  • Les principes et scripts sont transposables assez facilement à MS-Windows.
    • Pour ce dernier, je vous conseille d'installer au plus vite un environnement Posix.
    • Vous avez le choix entre Cygwin et MSYS/Mingw (j'ai une petite préférence pour ce dernier couple).
    • Je signalerai par une note les adaptations à faire sous MS-Windows.



Choix de l'émulateur

  • Sous Unix, le choix est rapide: hors OpenMSX, point de salut.
  • Sous MS-Windows, vous pouvez utiliser MSX Blue qui a très bonne réputation (mais n'est pas multiplateformes).
  • Je supposerai que OpenMSX est correctement installé, et qu'il tourne avec un vrai bios MSX.
    • En effet, par défaut il tourne avec C-Bios, qui émule les fonctions Bios, mais ne donne pas accès au basic.
    • Ceci étant génant (le basic nous servira toujours un peu), mieux vaut un vrai bios d'origine.



Choix de l'éditeur texte

  • Vim. Des questions ?
    • En fait, vous pouvez utiliser ce que vous voulez, même Emacs.
    • Il faut juste que l'éditeur soit capable de traiter les fichier avec le format de ligne msdos (0xd 0xa).
    • Vim et Emacs ont été porté sur les plateformes les plus exotiques. C'est donc un investissement dont vous toucherez les intêrets pendant de longues années.



Et le cross-assembler ?

  • Le principe est d'utiliser un cross-compilateur sur votre système hôte, et de fournir les fichiers compilés à l'émulateur.
  • Ceci permet d'automatiser au maximum toutes les manipulations :
    • Le cycle édition / compilation / test / debuggage doit se faire naturellement, et ne pas être soumis à des manipulations continuelles.
  • Nous allons commencer par choisir un cross-assembler, l'automatisation du cycle de production sera abordée par la suite.
  • L'utilisateur MS-Windows utilise généralement tniASM.
    • Tout le monde aime ce cross-assembler, et son mainteneur est encore vivant et présent sur IRC.
    • Malheureusement, ce n'est pas porté sous Linux.
    • On le trouve ici http://tniasm.tni.nl
  • Par contre , pour Linux... aie aie aie!
    • Je ne pensais pas avoir autant de mal avec les cross-assemblers Z80 sous Linux.
    • Sans plus attendre, passons au gros morceau.




Choix du cross-assembler Z80 pour Linux


  • Voici les résultat de plusieurs jours d'expérimentations.
    • J'ai volontairement omis les cross-assemblers qui me paraissaient vraiment morts (ex: ZASM).
    • Si j'en ai oublié des moins morts, merci de le signaler.



ASmsx

  • Je commence par celui dont je n'ai pas trouvé le site officiel.
  • Les sources ne semblent pas disponibles, du moins dans les archives que j'ai récupéré.
  • Il semble même ne pas y avoir de version autre que MS-Windows.
  • Il permet de réaliser facilement des ROMs avec les différents mappers MSX.



Pasmo

  • Pasmo semble déconseillé.
  • Il comporte quelques bizarreries, notamment la nécessité de commencer le code par la directive org. Ce qui donne org $C000-7 pour sauter le stub qui vient ensuite.
  • Mais certains projets l'utilisent, comme le C-BIOS.
    • J'ai discuté avec quelques personnes gravitant autour du projet C-BIOS, ça n'a pas l'air d'être le fol enthousiasme. Plutôt un choix par défaut.
  • Je n'ai donc pas évalué Pasmo, certain de trouver mieux ailleurs.
    • La suite de mes recherches me laisse à penser que je l'ai peut être éliminé un peu vite.



Sjasm

Grandeur et décadence de Sjasm
  • Sjasm semble jouir d'un crédit assez étonnant dans la communauté msx.
  • En fait, les anciennes versions étaient fonctionnelles, mais les plus récentes sont une vraie catastrophe.
  • Je vais développer, pour ne pas être accusé de taper sans raison sur un bon produit, ou de ne rien comprendre à la programmation.
  • Sjasm peut s'utiliser à partir d'un binaire (qui semble fonctionner), ou a partir des sources.
  • Je préfère compiler quand les sources sont disponibles, cela donne souvent de meilleurs résultats.
    • Il s'agit ici de la version 0.42b8


Compilation de Sjasm 0.42b8
  • make donne des erreurs (je passe charitablement sur les warnings), notamment:
    • datastructures.h:50: erreur: ‘memcpy’ was not declared in this scope
    • (erreur répétée plusieurs fois dans ce même entête)
  • Explication: memcpy est considéré comme une fonction membre de Data.
    • Data(byte *n_data,int n_size) : _data(0), _size(n_size), _maxsize(n_size) { _resize(n_size); memcpy(_data,n_data,n_size); }
    • Ce n'est bien sûr pas le cas. Habituellement, memcpy est déclaré dans string.h.
    • Faut-il faire un include de ce fichier au début de l'entête fautif ?
    • memcpy n'est utilisé que dans datastructures.h, ainsi qu'un appel dans datastructures.cpp.
    • voici son prototype: void *memcpy (void *dest, const void *src, size_t n);
    • la véritable fonction memcpy renvoie un pointeur sur *dest
  • J'ai ajouté memcpy dans la classe Data (au début avant même le constructeur, dans les membres public bien sûr) :
    • void *memcpy (byte *dest, byte *src, size_t n);
    • et je l'ai défini ainsi dans datastructures.cpp:

void * Data::memcpy (byte *dest, byte *src, size_t n)
{
  for (int i=0; i<n; i++) dest[i]=src[i];
  return dest;
}


  • Toujours dans datastructures.c, on a ensuite une référence inconnue à memset (également déclaré dans string.h)
    • void *memset (void *s, int c, size_t n);
    • comprendre: rempli *s 'n' fois avec c
  • * C'était la seule référence. J'ai remplacé par une simple boucle.

//memset(_data+_size,0,nsize-_size);
 for (int i=0; i<nsize-_size; i++) _data[_size+i]=0;


  • Erreur suivante:
    • errors.cpp:58: erreur: ‘exit’ was not declared in this scope
    • toujours un include à ajouter:
    • #include <cstdlib> (et non pas stdlib.h) dans errors.cpp (après le include "sjasm.h")
  • Et maintenant, il manque stdio
    • fileio.cpp:37: erreur: ‘fopen’ was not declared in this scope
    • (puis ensuite fclose, fseek, ftell, fwrite. En gros, tout la bande des I/O de stdio.h). On se demande à quoi sert de faire du C++ si c'est pour reprendre toute la librairie standard du C.
    • On inclut #include <cstdio> (et non pas stdio.h) juste après le include sjasm.h au début de fileio.cpp.
  • Erreur suivante: valeur absolue
    • rawsource.cpp:449: erreur: ‘abs’ was not declared in this scope
    • prototype dans stdlib.h : int abs (int j);
    • Ca calcule une valeur absolue. Bon, on va le faire nous même.

  int absolute=_offset%al;
  if (absolute<0) absolute=-absolute;
  if (_offset%al) _offset+=al-absolute; //abs(_offset%al);


  • Celui là, il est joli: reader.cpp:73: erreur: ‘malloc’ was not declared in this scope
    • effectivement, il y a bien un malloc t: if (b.length()+1>64) bp=p=(char*)malloc(b.length()+1);
    • Bon un free doit trainer quelque part, au milieu des delete.
    • Vérifions tout de suite (grep free *). Ah tiens... non. memory leak en perspective ?
    • #include <cstdlib> , après le #include "sjasm.h" (la routine quoi)
  • Allez , c'est le dernier:

sjasm.cpp:134: erreur: ‘exit’ was not declared in this scope
sjasm.cpp:145: erreur: ‘exit’ was not declared in this scope

  • Allez, include cstdlib again.


  • Et voila. L'exécutable sjasm est construit.
  • Il compile bien au moins ? Petit test...
  • Ca a l'air de fonctionner.


Patch pour Sjasm 0.42b8
  • J'ai donc écrit un patch que vous pourrez appliquer directement sur les sources du 0.42b8 si le coeur vous en dit.
  • diff -urNb sjasmsrc42b8 sjasmsrc42b8.jseb >sjasm42b8.patch
    • Le résultat est un peu long pour être publié ici, je l'ai inclus sous forme de fichier.
  • Pour appliquer le patch:
    • Placez-vous dans le répertoire des sources de Sjasm, et copiez-y le patch
    • Lancez la commande patch : patch -p1 < sjasm42b8.patch
  • Une fois les fichiers patchés, vous pouvez lancer make (ne faites pas attention aux warnings, je n'ai pas corrigé cette partie).



Sjasmplus

  • Voyons voir Sjasmplus, qui est un fork d'une ancienne version de Sjasm.
  • Houlala, sur le site officiel, il y a un lien pour les recommended text editors.
    • Ok, ni Vim, ni Emacs, ni même Ultraedit. Ca commence bien. Je n'ai même pas envie de reprendre les sources pour tout dire.
  • Allez, courage.
    • Bon alors, il y a une stable, et une version de dev. La version de dev n'inclue pas le scripting avec Lua.
    • Je reprends la stable, on verra la version de dev plus tard, éventuellement.
  • La version stable est la 1.06 (3 aout 2006)
  • Je lance la compilation.
    • A première vue, autant de warnings que chez son petit frère Sjasm.
    • Ah, et voici les premières erreurs:

Sjasm.cpp:167: erreur: ‘MAXPATHLEN’ was not declared in this scope
Sjasm.cpp:199: erreur: ‘zoekpad’ was not declared in this scope

  • Là j'avoue, je n'ai pas trop cherché.
    • car c'est alors que je suis tombé sur ça:

#ifdef WIN32
int main(int argc, char *argv[]) {
#else
int main(int argc, char **argv) {

  • Il se faisait tard, j'ai laissé tomber.
  • Je me demande à quoi pensait le type qui a écrit ça.



z80-asm

  • z80-asm, avec un tiret dans le titre
    • Je précise pour le tiret, car il a un homonyme sans tiret (qui est le prochain abordé).
  • Le problème est sa rigidité syntaxique.
    • Il ne veut pas des instructions db de mon programme de test.
    • Il faut remplacer les db par des defb, les dw par des defw, etc...
    • Les strings ne sont admises qu'avec une déclaration defm (defb ne passera pas).
  • Pour illustrer ce problème, cette déclaration sera refusée:

LABEL: defb "Hello",13,10,0

  • Et il faudra l'écrire comme ceci:

LABEL: defm 'Hello chput'
       defb 13,10,0 

  • Attention, pour avoir l'aide, c'est -h. Et non pas --help ou -help.
  • Si vous ne précisez pas de fichier de sortie, la syntaxe du programme sera vérifiée, mais vous aurez le message: No code generated même si vous n'avez pas d'erreur.
  • Par défaut, z80-asm rajoute un header qui empêche toute exécution par le msx, et il prend au pied de la lettre la directive org $c000 en générant un binaire de 48 Ko!

jseb ~/msx $ hexdump -C test-z80-asm.bin
00000000  5a 38 30 41 53 4d 1a 0a  00 00 fe 00 c0 1b c0 00  |Z80ASM..........|
00000010  c0 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
00000020  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
*
0000c000  00 00 00 00 00 00 00 00  00 00 21 0d c0 7e 23 a7  |..........!..~#.|
0000c010  c8 cd a2 00 18 f7 c9 48  65 6c 6c 6f 20 63 68 70  |.......Hello chp|
0000c020  75 74 0d 0a 00                                    |ut...|
0000c025

  • Pour les informations sur le header, voir dans la doc: z80-file.5 (ou man z80-file si vous avez installé les pages man).
    • En gros, il faut enlever les 10 premiers octets.
  • Pour comparaison, le même programme généré avec Sjasm.

jseb ~/msx $ hexdump -C sjasm.bin
00000000  fe 00 c0 1b c0 00 c0 21  0d c0 7e 23 a7 c8 cd a2  |.......!..~#....|
00000010  00 18 f7 c9 48 65 6c 6c  6f 20 63 68 70 75 74 0d  |....Hello chput.|
00000020  0a 00                                             |..|
00000022

  • Je n'ai pas trouvé la façon d'enlever l'entête dans le manuel de z80asm.
    • Du coup, je l'ai fait moi même avec un coup de dd.
    • dd if=test2.bin of=raw.bin ibs=1 skip=10
    • Mais ne vous fatiguez même pas à essayer. Le code ne s'exécutera bien sûr pas dans l'émulateur.
  • Dommage, cet assembleur semblait un bon candidat, abstraction faite de sa syntaxe rigide.
    • Le package possède également un moniteur, déja évoqué ci-dessus.
    • Cela dit, rien ne vous empêche d'utiliser le moniteur et de compiler avec un autre cross-assembler.



z80asm

  • Un bon petit cross-assembler, un peu limité mais à l'approche facile.
  • Le nom ressemble fortement au précédent, et se différencie par l'absence de tiret (ça devient subtil).
    • Mais cette fois, nous avons affaire à un produit plus utilisable
  • Bonne surprise, le code source compile sans erreurs ni warnings.
  • Certaines fonctionnalités sont absentes:
    • Exemple tiré du manuel: rlc r,(ix+nn) and friends don't work
    • Cela ne me parait pas bien grave, et il y a toujours possibilité de faire une macro pour assembler directement l'instruction en écrivant les octets des instructions avec une séquence db.
  • Côté directives, c'est le minimum syndical: defb/db, defwdw, ds/defs , include, if/else/endif.
    • Pas de macros ni de incbin pour ajouter directement des fichiers binaires.
    • Pour incbin, ce n'est pas bien grave. On peut transformer des données binaires en db/dw, et les inclure avec la directive include.
  • Mon programme de test a été assemblé sans problèmes, sans adaptations syntaxiques, et a parfaitement fonctionné sous OpenMSX.
  • Bien que limité, z80asm semble être un bon choix pour le programmeur pressé de faire ses premiers programmes.



WLA DX : le meilleur pour la fin

Des caractéristiques alléchantes
  • C'est un projet vivant avec des patches récents (aout 2010).
  • Ce cross-assembler supporte d'autres processeurs que le Z80 (6502, 6510 ...)
    • Pour ne rien vous cacher, la désignation complète est Yet Another GB-Z80/Z80/6502/65C02/6510/65816/HUC6280/SPC-700 Multi Platform Cross Assembler Package.
  • A noter que la compilation et le link sont séparés, ce qui permet de linker des objets entre eux, ou des libs.
    • Cette séparation des commandes parait aller de soi, mais elle est absente des cross-assemblers que j'ai testé jusqu'à présent.
    • Pour plus de détails, référez-vous aux sections compiling et linking dans le README (section 9 et 10).
  • Les possibilités offertes par les directives disponibles sont impressionantes.
    • Attention, il y a quelques pièges que je détaillerai plus loin.
  • La doc n'est pas toujours très claire, mais elle est complète.
    • Il ne faudra pas hésiter à faire quelques allers-retours dans la doc. Les informations sont parfois un peu éparpillées.


Compilation de WLA DX
  • Compilateur et linkers étant séparés, il va falloir procéder en deux temps.
  • La dernière version sur le site de Ville Helin (son auteur) est la 9.5 (aout 2008).
  • Depuis, il est hébergé sur sourceforge.
    • Le mieux est de récupérer les derniers commits avec subversion depuis le repository:
    • svn co https://wladx.svn.sourceforge.net/svnroot/wladx wladx
  • Il faut ensuite aller dans le répertoire makefiles, et choisir celui qui nous intéresse.
    • Dans notre cas, il s'agit bien sûr de makefile.unix.z80
  • Copier ce makefile dans le répertoire des sources du compilateur (répertoire racine \"wladx\").
    • Modifiez le pour virer le flag -O3 et mettre un -O2 à la place.
  • make clean && make -f makefile.unix.z80
    • Le make clean est là au cas où une autre architecture aurait été compilée auparavant.
    • Ainsi, le define -DZ80 sera bien pris en compte.
  • Pas de warnings inquiétants à signaler (n'oublions pas que les flags sont assez durs: -ansi -pedantic -Wall ! )
    • Lancez l'exécutable obtenu (wla-z80).
    • La première ligne doit indiquer qu'il s'agit de la version Z80 :

/tmp/wladx$ ./wla-z80 

WLA Z80 Macro Assembler v9.5

  • Si vous obtenez la ligne ci-dessus, le compilateur est prêt.
  • Il reste à s'occuper du linker, qui lui est commun à tous les compilateurs supportés par WLA.
    • Le linker se trouve dans le sous-répertoire wlalink
  • Il faut modifier wlalink/makefile.unix sur deux points:
    • Remplacer -O3 par -O2 (comme pour le compilateur).
    • Remplacer $(LD) par $(CC) (sinon la compilation plante lors du link sur la libc).
  • Vous pouvez maintenant faire un:
    • make clean && make -f makefile.unix
    • L'exécutable obtenu se nomme wlalink

/tmp/wladx/wlalink$ ./wlalink                                                  e

WLALINK GB-Z80/Z80/6502/65C02/6510/65816/HUC6280/SPC-700 WLA Macro Assembler Linker v5.7

  • Et voila, le linker est prêt également.



Test de WLA DX
  • WLA DX a une approche assez originale qui peut dérouter au premier abord.
  • Avant toutes choses, lecture (même rapide) obligatoire du README (91ko!) qui fait office de documentation principale.
  • Voici un programme de démonstration adapté à WLA DX, avec quelques explications.
; test.asm - for testing WLA cross compiler.
; jseb @ finiderire . com

.MEMORYMAP
SLOTSIZE $FFFF
DEFAULTSLOT 0
SLOT 0 $0
.ENDME

.ROMBANKMAP
BANKSTOTAL 1
BANKSIZE $FFFF
BANKS 1
.ENDRO

.section "BANKHEADER"
  .db $fe
  .dw start,end,start; 
.ends

.BANK 0 SLOT 0
.ORG $C000 

start:
     LD HL,label
aff: LD A,(HL)
     INC HL
     AND A
     RET Z
     CALL $A2 ; CHPUT
     JR aff
     RET

label: .DB "Hello, World",13,10,0
end: .equ $-1


  • Au début du programme, vous remarquez quelques directives:
    • .MEMORYMAP et .ROMBANKMAP
    • Elles servent à définir la structure des roms. Ici, j'ai fait au plus simple (un seul slot, une seule banque, la totalité de l'espace adressable par un Z80 assigné sur le même slot).
  • BANKHEADER est plus intéressant, et nécessaire pour écrire le stub de notre programme.
    • les octets contenus dans BANKHEADER seront simplement ajoutés au début de l'objet, et ne provoqueront pas de décalage dans le calcul d'adressage à la compilation. Dans la doc, il est même précisé que c'est une option très utile pour le MSX (tu m'étonnes).
  • Le .BANK 0 SLOT 0 ne semble pas obligatoire, car notre cas est très simple. Mais dans d'autre cas, il peut être utile de spécifier la BANK ou le SLOT. J'ai donc laissé cette directive pour attirer votre attention sur son existence.
  • A propos de BANK et de SLOT, la terminologie employée ici n'ait aucun rapport avec le memory mapping du MSX , même si les mots sont identiques.
  • Avant de nous lancer dans la compilation et le link, un gris piège est à signaler:
    • .equ est un alias pour .define
    • c'est à dire: .define : Assigns a number or a string to a definition label.
    • Dans l'exemple en dessous, on met donc start à zéro! Ce n'est pas le comportement habituel qui serait d'assigner la valeur de start à exec.
    • exec: .equ start ;en réalité, met start à zéro !!
    • Il semble qu'on ne puisse pas assigner de valeur à une étiquette en utilisant la valeur d'une autre étiquette. Par contre, on peut faire ça: exec: .equ $C000
    • Ce qui n'a pas un grand interet (voire même peut être dangereux si on change la valeur de .ORG )


  • Pour la compilation :
    • wla-z80 -o test.asm
    • le flag -o sert à demander la génération d'un fichier objet.
    • le nom du fichier objet est par défaut celui du fichier source avec l'extension .o
  • Pour le link :
    • wlalink -b test.group test.bin
    • le flag -b est important, car par défaut, c'est -r qui est utilisé. Et le flag -r sert à créer une rom.
    • Le fichier test.group contient différents paramètres, dont le nom des fichiers objets à utiliser pour le link (voir la doc).
    • Ici, le fichier test.group contient ceci:

[objects]
test.o

  • Il est réduit ici à sa plus simple expression.
  • Voilà un tour rapide de WLA. Vous en savez assez pour lire la doc et pouvoir m'expliquer comment générer une ROM avec ce compilateur!



Le cas des macro cross-assemblers

macro quoi ?
  • Un macro cross assembler est un cross compilateur classique, mais qui fonctionne avec un système de macros.
  • Les macros sont des regroupements d' instructions (ici, les mnémoniques), sous une seule instruction afin de faciliter la lecture.
  • Une macro sert à automatiser l'insertion d'un bloc d'instruction.
  • Le support par le compilateur des macros peut être plus ou moins étendu:
    • Cela peut aller du simple remplacement de texte (comme une fonction inline) à l'intégration de la gestion des opérateurs arithmétiques et logiques.
  • Notez qu'il existe bien sûr des macro assemblers dédiés à la plateforme hôte. Ils ne sont donc pas cross-compilers.
  • Les macro-assemblers permettent d'introduire un peu de haut niveau dans le monde aride de l'assembleur.
    • Le revers de la médaille peut être une génération de code bien foireuse, surtout pour des projets amateurs peu suivis.


Le macro cross-assembler AS
  • AS rentre dans le club très fermé décrit ci-dessus.
  • Son support des macros est suffisament étendu pour justifier un traitement à part.
  • Vous le trouverez ici:
  • Voici un exemple de sa syntaxe

dbstr   macro   arg
        if      strlen(arg) > 1
         db     substr(arg, 0, strlen(arg) - 1)
        endif
        if      strlen(arg) > 0
         db     charfromstr(arg, strlen(arg) - 1) | 80h
        endif
        endm 

  • Il m'a l'air ma foi fort intéressant...
    • mais j'avoue que je commence à me lasser de tous ces tests.



Mes choix de cross-assemblers

  • Il faut bien choisir, alors voici mes préférés.


WLA DX, le meilleur et le plus exigeant
  • WLA DX est de loin le meilleur cross compiler que j'ai pu tester. Il y a un monde entre lui, et Sjasm par exemple.
  • Ses avantages:
    • Le compilateur et le linker sont séparés, ce qui est une très bonne chose.
    • Il compile sans warning inquiétants, ni erreurs, avec des flags qui ne pardonnent pourtant pas.
    • La doc est bien fournie.
    • Il est maintenu et réellement multi-plateformes, signe d'une bonne conception.
    • Le code est en C, preuve de bon goût (mieux vaut écrire du C rustique et fonctionnel que du C++ qui compile à peine).
    • Seule une relative complexité pourrait vous conduire à lui préférer z80asm (celui de Sheveks).
  • Ses inconvénients:
    • Une façon de faire aux antipodes de la simplicité.
    • Une doc pas toujours très claire.
    • Nécessite surement un peu d'expérience en programmation pour être apprécié.


z80asm, rustique mais efficace
  • Celui-ci est simple, mais n'a posé de problèmes ni à la compilation, ni à l'utilisation.
  • D'autres part, il a été développé spécifiquement pour être utilisé avec un MSX.
    • Cependant, contrairement à ASmsx, il ne permet pas de créer facilement des ROMs.
    • Seuls quelques fichiers d'équivalences spécifiques aux MSX sont fournis.
  • Sa rusticité (peu de directives disponibles) ne doit pas faire oublier sa facilité d'emploi.


Sjasm 0.42b8, le pari
  • Avec Sjasm, vous avez un cross-assembler relativement séduisant sur le papier.
  • Ses sources font cependant assez peur, et le patch que je vous propose pour le compiler ne corrige que les erreurs bloquants la compilation.
  • Une fois que j'ai réussi à le compiler, mes programmes de tests sont passés sans problèmes.
  • A tester donc, pour les plus joueurs d'entre-vous.


Et pour les Windoziens, c'est tniASM
  • tniASM semble pas mal... pour MS-Windows.
    • je continue à tanner son auteur sur IRC pour une version OpenSource.




Fini pour aujourd'hui


  • Le prochain sujet abordé sera l'échange de données avec l'émulateur, et l'édition facile d'un programme basic.
  • D'ici là, vous avez le temps de digérer ce billet un peu long.
    • Vous pouvez même retourner sur la plage, le temps que j'écrive tout ça, les nuages sont partis.
  • Votre propre expérience des cross-assemblers m'intéresse! N'hésitez pas à poster vos remarques et ajouts.