-(G)-(E)-(M)-(A)- [G]enPC [E]lite [M]acro [A]ssembler (C)oderite SECTOR ONE 1994-95 Documentation francaise de la version 2.6 I. Introduction 1. Shareware 2. Credits 3. Greetings II. Generalites 1. Modes d'adressage 2. Arithmetique 3. Directives d'assemblage III. Mnemoniques IV. Conclusion --==-- I. Introduction _______________ GenPC alias GEMA est un nouvel assembleur symbolique pour MS-DOS. Il est tres largement inspire de la reference en matiere d'assembleur : GenST sur Atari. De plus les normes et mnemoniques Intel ont etees un peu adaptes a la norme Motorola 680x0 qui est beaucoup plus simple et logique. Contrairement a TASM qui se donne un style pseudo-structure qu'on doit trainer comme un boulet, qui buggue a mort sur les instructions 386+, et qui ne nous laisse pas vraiment controler l'assemblage des mnemoniques, GEMA vous laisse libre de coder comme des porcs et doit bugger un peu moins. Il supporte desormais tous les opcodes des processeurs Intel, du 8086 au P6, y compris les opcodes non documentes ! De plus il est beaucoup plus rapide que TASM, ne necessite pas de linker, et possede des directives d'assemblages tres pratiques, en particulier le INCBIN qui a toujours fait atrocement defaut sur TASM et MASM. Si vous ne codez pas encore en assembleur, GEMA est celui qu'il vous faut pour vous initier a la joie (heu...) des 80x86. De plus vous n'aurez aucun mal a passer au 680x0 par la suite. Si vous codez deja en 680x0 vous n'aurez pas a vous prendre la tete pour ingurgiter les bizarreries d'Intel et ne serez pas degoutes que TASM soit aussi lourd a utiliser que les 80x86 sont complexes. Si vous codez deja en 80x86, vous devez en avoir marre de TASM et MASM. GEMA est l'assembleur qu'il vous faut ! Il est particulierement adapte a la programmation en mode flat (V86) ou protege et est tres simple a utiliser en 32-bits contrairement aux assembleurs cites precedemment. Un environnement avec un editeur sympa du style Borland C++ et la possibilite d'assembler et de debugguer directement en memoire, est en finition. I.1 Shareware _____________ GEMA est un SHAREWARE. L'installer sur votre disque dur implique de votre part l'acceptation des conditions suivantes : - Si vous travaillez au Centre de Facturation et de Recouvrement de France- Telecom a Savigny, vous devez faire sauter ma derniere facture, ainsi que les suivantes si possible, - Si vous aimez le COBOL vous devez vous tirer une balle, - Si vous etes surveillant a l'Epita, vous ne devez pas m'accuser a tort de gruger pendant les interros, - Si vous etes un coder, graphiste, zikos ou courrier solitaire, vous devez entrer dans Sector One, - Si vous etes une jeune fille d'une vingtaine d'annees, vous devez etre folle amoureuse de moi, - Si vous pouvez avoir du matos pas cher, vous devez m'en faire part, - Si vous trouvez des bugs vous devez aussi m'en faire part, - Si vous n'en trouvez pas c'est que vous ne l'avez jamais utilise, c'est mal, A propos, cette version n'est qu'une beta donc si il reste des bugs c'est normal mais n'hesitez pas a me les signaler en precisant bien ce que vous avez fait, ce qui aurait du se passer et ce que vous avez a la place, ainsi que la date de votre version de GEMA. Les points suivants en particulier ne fonctionnent pas encore (c'est pas un bug c'est la flemme), mais ne sauraient tarder : - Instruction CMPXCHG que je n'ai jamais reussi a assembler avec TASM, - Macros : uniquement presentes dans les versions enregistrees : Si vous desirez vous enregistrer en tant qu'utilisateur legal de GEMA, envoyez la modique somme de 50 F a l'adresse figurant plus bas. Vous beneficierez alors des avantages suivants : - Vous aurez bonne conscience, - Vous encouragerez l'auteur a continuer de coder des sharewares, - Vous recevrez en avant-premiere les mises a jour par InterNet ou par courrier, - Votre nom ou pseudo sera cite dans les prochaines versions. Ca me ferait aussi tres plaisir de recevoir des programmes codes avec GEMA... I.2 Credits ___________ Assembleur : Doc, code, gfx (Heu...), musique (Ou ca ?) ...... Jedi/Sector One Support moral : .................................................... Stephanie Correction des fautes d'orthographe de la doc francaise ................ Mogar Softs utilises : Qedit, Gema, Hacker's View, DJGPP Beta-testeurs : MJS, Altomcat/Sector One, ODC/Sector One, Createur/Eko, Oxygene, Keops/Equinox, Alexey Voinov Vous pouvez nous contacter a l'adresse suivante : Frank DENIS 2, Rue Madeleine Laffite F-93100 MONTREUIL Ou sur RTEL, bal SECTOR ONE, JEDI/SECTOR ONE ou ODC, Ou par Email : j@nether.net Vous pouvez recevoir la derniere version de l'assembleur par InterNet en envoyant un E-Mail avec le sujet GET GEMA a l'adresse precedente, ou par ftp sur ftp.nether.net dans le repertoire /pub/gema/* . Il est aussi disponible en telechargement gratuit sur ACE BBS au [+33] (1) 45 88 75 48 et par FidoNet avec le mot-cle GEMA sur la node 2:320/305. Vous pouvez aussi le telecharger par Minitel au prix d'un simple appel sur Paris sur RTC-One au (1) 48 70 10 29 ou (1) 48 58 46 17 ( acces V34 possible au (1) 49 88 76 91 ) . GEMA doit trainer sur d'autres BBS et FTP mais c'est avec les moyens precedents que vous avez le plus de chances d'avoir la derniere version le plus rapidement possible. Mais par pitie ne me telephonez pas... I.3 Greetings _____________ Un gros bisou a : Infiny (LCA), Eclipse (Hacker Croll), CyberPunk (qui m'a tout appris d'Unix et du C), Gerald (merci pour les bouquins sur le C++), Trash, Dream Syndicate, Underground Tectonics (Sexo, Online, Clocky), Eko (Maxx, McDo, Createur), Eagles (Ard), Equinox (Checksum, Al Cool, Keops), Lego System (Skill), Dune (Meerclaw, Evil Metal, Chuck, Floopy...), Fantasy (Deneb, Remalon : Hep faut vous mettre a l'asm), Genesis (Lachez le TP), DBA (Bonus Software), Sentry (Eagle), Isiolis, Imphobia, Dead Hacker Society, Control Team, Quicky, Anixter, Fantasy, Live!, Fongus, Bresil, DSK, Alexey Voinov, Oxygene, Jared, Impact Studios, Kloon, Antares, Pulse, RealTech, Animal Mine, Oxyron, Max in the Star System, Epsilon, EMF, Plant, Cascada, Cubic Team, et a vous... Une liste plus complete est disponible dans la version anglaise de la doc. II. Generalites _______________ GEMA necessite un 386, un 486, un Pentium ou un P6 (32 bits oblige). Il prend un ou deux parametres qui sont le nom du fichier source et eventuellement le nom du fichier executable. Genre : gema youpla.s ou : gema youpla.s yahoga.exe Si il n'y a pas de second parametre, le fichier cree sera le nom du fichier source avec l'extension EXE ou COM. Quelques options peuvent preceder les noms de fichiers : -E ou --preprocess : affiche chaque ligne traitee -v ou --verbose : affichage etendu -q ou --quiet : affichage reduit -o ou --optimize : optimisations automatiques ( 3 passes necessaires ) -nw ou --nowarning : n'affiche plus les warnings -a ou --autoalign : alignement automatique ( experimental ) -86, -88, --cpu=86 ou --cpu=88, -186 ou --cpu=186, -286 ou --cpu=286, -386 ou --cpu=386, -486 ou --cpu=486, -586, -pentium, --cpu=586 ou --cpu=pentium, -686, -p6, --cpu=686 ou --cpu=p6 : assemble uniquement les opcodes reconnus par le type de processeur designe. Par default, toutes les instructions du 8086 au p6 sont reconnues. II.1 Modes d'adressage ______________________ Les modes d'adressage sont au format Motorola 680x0, a savoir : Designation Intel GEMA ------------------------------------------------------------------ Immediat court 12 #12.b Immediat (mot) 32000 #32000.w Immediat (mot long) 99999 #99999.l .b, .w et .l sont facultatifs, il permettent en fait de forcer un type, par exemple pour faire reconnaitre une valeur qui se coderait sur un octet comme un mot long, indispensable pour le code automodifiant. Si on ne precise pas la taille, GEMA determine automatiquement la plus petite. Designation Intel GEMA ------------------------------------------------------------------ Direct Ah, Bx, Ecx, Si, Cs Ah, Bx, Ce, Si, Cs Sous GEMA, les registres ont la meme designation que sous TASM en dehors des registres 32-bits qui sont de la forme : Ae, Be, Ce, De, Sie, Die, Bpe et Spe. C'est plus logique comme ca. MAIS dans la plupart des cas, les seules lettres A, B, C ou D suffisent. Car comme en 680x0, c'est dans l'instruction qu'on determine la taille des operandes et GEMA adapte les operandes automatiquement. Ainsi : NEG.B A sous GEMA equivaut a NEG AL sous TASM Par defaut une instruction .B sur un registre indetermine equivaut a AL,BL,CL ou DL. Si c'est AH, BH, CH ou DH, il faut evidemment mettre le registre complet, Ex: NEG.B AH NEG.W A sous GEMA equivaut a NEG AX sous TASM Sauf pour les instructions qui ne prennent pas de mots comme operandes, la taille par defaut est le mot. Par consequent NEG.W A ou NEG A sont identiques. C'est valable pour la quasi-totalite des instructions. NEG.L A sous GEMA equivaut a NEG EAX sous TASM Dans tous les cas on peut bien entendu mettre le registre en entier a la place du registre indetermine. Par exemple NEG.L EAX marche impec. Par contre NEG.L AX va vous balancer une erreur car la taille du registre est incoherente avec la taille de l'instruction. Si vous trouvez que c'est plus complique de preciser la taille dans l'instruction que de la sous-entendre avec la taille des operandes, vous n'avez rien compris a la vie. Car d'une part c'est plus clair comme ca, d'autre part vous n'avez pas a vous taper des WORD PTR et autres en cas d'ambiguite. Ainsi : NEG.L (SI,DI) sous GEMA equivaut a NEG DWORD PTR [SI+DI] sous TASM Ah tiens j'allais oublier ... A la place de .b vous pouvez utiliser .s c'est pareil ... C'est juste histoire de rester dans les normes de GenST. Designation Intel GEMA ------------------------------------------------------------------ Absolu court [12] 12.b Absolu (mot) [32000] 32000.w Absolu long [99999] 99999.l La encore les .b .w et .l sont facultatifs, ils ne sont utiles que pour forcer un type. Autrement l'assembleur les determine tout seul comme un grand. Sous GEMA comme en 680x0, et etant donne que l'immediat est prefixe, une adresse absolue n'a pas de prefixe. C'est aussi valable pour les labels : NEG label sous GEMA equivaut a NEG WORD PTR [label] sous TASM. Designation Intel GEMA ------------------------------------------------------------------ Indirect [Si] (Si) Indirect avec registre [Si+Bx] (Si,Bx) ou (Si,B) La taille par defaut des registres d'index indetermines est un mot. Designation Intel GEMA ------------------------------------------------------------------ Indirect avec reg et offset.b [Si+Bx+12] 12.b(Si,Bx) Indirect avec reg et offset.w [Si+Bx+32000] 32000.w(Si,Bx) Indirect avec reg et offset.l [Esi+Ebx+99999] 99999.l(Sie, Be) Comme d'habitude les .b .w et .l sont pour le forcage uniquement. Par exemple 12(Si,Bx) est strictement equivalent a 12.b(Si,Bx). C'est donc inutile de le preciser la plupart du temps, on peut balancer l'offset tel quel, GEMA se debrouillera. Designation Intel GEMA ------------------------------------------------------------------ Indirect reg/off/facteur [Esi+Ebx*facteur+off] off(Sie,Be*facteur) Bon la je precise pas mais l'offset ca peut etre un .b un .w ou un .l comme au dessus ... Au passage le facteur ne marche qu'avec des registres 32-bits ainsi que les offsets longs ... L'ARGUMENT SOURCE EST TOUJOURS LE PREMIER, L'EVENTUEL ARGUMENT DESTINATION TOUJOURS APRES. Ainsi sous GEMA, pour mettre le contenu de AX dans BX il faut faire : MOVE A,B (ou MOV A,B) et non pas l'inverse comme dans TASM. Evidemment pour des instructions genre ENTER ou il n'y a pas d'argument source et destination, l'ordre est le meme que dans TASM. Pour toutes les autres c'est au format motorola soit l'inverse de TASM. II.2. Arithmetique Tous les operateurs classique sont utilisables pour les offsets et immediats. Par ordre de priorite decroissante (Ouaip ca gere meme les priorites) : []: Ce sont les parentheses ... - : Oppose d'un nombre < : Decalage gauche. Ex : 3<2 renvoit 12 > : Decalage droit. 6>1 renvoit 2 ^ : OU exclusif & : ET logique | : OU logique / : Division * : Multiplication - : Soustraction (Ouaip il distingue les deux types de '-') + : Addition % : Modulo = : Egalite : renvoit 0 si fausse et 1 si vraie. @ : Divise par 16 ce qui suit. Par exemple @Toto donne l'offset de segment du Label Toto. Les @ sont accumulables, par ex @@Toto renvoit Toto divise par 256. ~ : NON logique \ : Retourne l'adresse de segment ce qui suit. La valeur sera forcement traitee comme un mot et sera relogee si le programme est un .EXE . C'est un peu l'equivalent du prefixe SEG sous MASM et TASM. : : (Oui c'est le signe ':') Versions < 2.5b : retourne les 4 bits de poids faibles de ce qui suit, un peu comme le prefixe OFFSET de MASM et TASM. Versions >=2.5b : retourne ce qui suit modulo la taille de segment courante. Ceci a ete modifie par soucis de compatibilite avec A2G. Cet operateur n'a en pratique pas grand interet ... Exemple: 2+3*4/[-5-7]<[~3^5] En dehors des nombres on peut utiliser bien d'autres choses au sein d'operations arithmetiques : * : L'asterisque peut aussi representer l'adresse de l'instruction, ou tout au moins son offset par rapport au debut du programme. { Exemple : bra.s * equivaut a : toto jmp toto } '': Code ASCII d'un ou de plusieurs caractere. { Exemple : 'A' est equivalent a 65. 'AB' est equivalent a $4142 } } Bases : Un nombre entre directement est toujours interprete en decimal. { Exemple : 12 comme ca, c'est en base 10 pour GEMA. } Pour l'hexa, il suffit de le faire preceder d'un $ (c'est moins debile qu'un 'h' a la fin avec quelque fois un 0 au debut pour eviter des confusions). { Exemple : Sous GEMA, $ABCD1234 est equivalent a 0ABCD1234h sous TASM. } Un nombre binaire doit commencer par un %, { Exemple : %101 vaut 5. } Un nombre octal doit commencer par un signe 'paragraphe' que je n'ai malheureu- sement pas sur mon clavier actuel. Bah de toutes facons ca sert a rien l'octal. On peut bien evidemment faire des operations melangeant plusieurs bases. Le forcage est possible sur toute expression, { Exemple : [1+$12A/%10001001].b } Mais peut aussi etre fait sur un seul terme au sein de l'expression, { Exemple : $1234.b+1 vaut non pas $1235 mais $35 car le .b a reduit le terme $1234 a un octet. } GEMA peut donc evaluer des operations tordues dans toutes les bases avec des forcages de types dans tous les sens, no problemo. Les resultats obtenus peuvent etre utilises n'importe ou en tant que constantes, offsets ou immediats. Mais GEMA ne traite pas que des nombres, il peut aussi evaluer des symboles. Symboles : Il en existe 3 types sous GEMA : - Les labels. Le format d'une ligne d'instruction sous GEMA est : [Label] [Instruction] [Arguments] [Commentaire] Si on declare un label, il faut le faire imperativement en debut de ligne. Les deux points qui suivent sont facultatifs. Une instruction ne doit jamais se trouver en debut de ligne, mais au moins apres des espaces et/ou tabulations. Une instruction qui se trouve en debut de ligne sera interpretee comme un LABEL (Oui on peut utiliser des mots reserves comme labels ou variables, pas de probleme). Le commentaire n'a pas toujours besoin d'etre precede d'un point virgule, mais une ligne de commentaires sans instruction doit commencer (donc a la place du label) par un asterisque, un point virgule, un pourcent ou un slash. { Exemples : Toto move.l a,b ceci est un commentaire addx (si,bx),c Tut bra.s Tut youpla * Ligne de commentaire / Autre ligne de commentaire Pouet: nop } Parfois, un point virgule est neanmoins necessaire pour un commentaire place a la fin d'une ligne d'instruction. Ainsi : rts tititata cherchera a evaluer tititata, vu que l'instruction rts peut etre utilisee aussi bien seule qu'avec un argument. Contrairement a : rts ; tititata Ou tititata sera ignore comme tout bon commentaire digne de ce nom. On peut mettre des espaces un peu partout, GEMA va les ignorer, { Exemple : addx.l 4 + 3 / [ 1 + 2 ] ( sie , be * 8 ) , d } Par contre on ne met jamais d'espace entre une instruction et un eventuel indicateur de taille (addx.l et pas addx . l) . Le label START est toujours defini comme label nul, il represente le debut du programme et peut etre utilise par les maniaques au meme titre que NULL en C ... Un label peut etre utilise au sein d'une expression arithmetique. Il a dans ce cas pour valeur son offset par rapport au debut du programme, moins la valeur d'ASSUME (On verra ASSUME plus tard) + la valeur du dernier ORG (Ca aussi on verra plus tard) . { Exemple : Toto move.l #Toto-Tata/2,Toto+2 Tata flush } Un tel label ne peut etre defini qu'une fois dans le source faute de quoi GEMA vous signalera l'erreur. Il a une valeur constante pendant tout l'assemblage, contrai- rement aux labels locaux et aux variables. - Les labels locaux : C'est pareil que les labels globaux sauf qu'on peut les redefinir. Leur nom doit commencer par un point. C'est assez utile pour les boucles, { Exemple : move #$1234,c .wait dec c bne .wait identique a jnz ...plein d'instructions... move a,c .wait nop cmps.b dbeq .wait identique a loopnz } Ils peuvent etre employes au sein d'expressions arithmetiques et ont pour valeur la derniere fois ou ils ont ete definis avant le calcul. On peut aussi leur assigner une valeur constante grace a la directive SET : { Exemple : .wait set $1234 } Et zou, le label local .wait vaut $1234. Par contre avant d'etre affecte par la constante, il vaut la valeur de l'offset de l'instruction comme tout bon label. Et alors me direz-vous ? Bin si vous faites par exemple: { .wait set .wait+2 } Vous pouvez faire ca plusieurs fois de suite, .wait va toujours valoir deux octets de plus que sa derniere declaration. C'est hyper utile pour le code automodifie. Imaginons maintenant une autre situation, ou vous devez faire une table des multiples de 3. On verra plus bas que les instructions REPT...ENDR permettent de repeter un bout de code et que DC.L permet d'inserer dans l'objet un mot long constant (comme DD sous TASM). Ce qui serait interessant c'est que .wait vale eventuellement la valeur de l'endroit ou il se trouve lors de sa premiere declaration, et qu'il ne soit plus affecte que par la valeur du set par la suite. GEMA le permet et ce sont les variables d'assemblage. - Les variables d'assemblage Leur nom commence par un point d'exclamation. Elles peuvent etre utilisees comme les labels. Ce sont des labels locaux qui ne sont affectes par l'offset ou ils se trouvent qu'au premier assignement. Ainsi pour faire notre table de 3 sur 256 mots longs. { Exemple: !Toto set 0 rept 256 dc.l !Toto !Toto set !Toto + 3 endr } Merveilleux non ? Dans une meme expression on peut bien entendu melanger les trois types de symboles et peut forcer leur type. Les mots reserves sont utilisables et tous les caracteres sont significatifs. Majuscules et minuscules sont differenciees. Les caracteres admis sont les lettres, les chiffres, l'underscore (_), le point d'exclamation et le point. II.3. Directives d'assemblage Elles se placent en seconde position comme toute instruction. - REPT ...ENDR Permet de repeter plusieurs fois un bout de code. { Exemple: rept 5 nop xlat endr } Et zou on aura : nop xlat nop xlat nop xlat nop xlat nop xlat - SET Deja vu. - ORG Permet de fixer un offset de base. Bah c'est comme sous TASM ou n'importe quel assembleur, sauf que sous GEMA vous pouvez en mettre ou vous voulez meme si ca n'a d'interet qu'au debut d'un programme. { Exemple : org $100 (GEMA accepte aussi org #$100) } - TITLE titre Donne un titre au fichier source en cours. Actuellement inutilise. - USE16 Indique que le code qui suit sera dans un code en 16 bits par defaut ( necessite d'employer des prefixes pour les acces 32 bits ) - Par defaut. - USE32 Le code qui suit est suppose se trouver dans un segment de code en 32 bits. Ceci n'est possible qu'en mode protege. - OPT Active ou desactive certaines options. Prioritaire par rapport aux options entrees en ligne de commande. OPT o+ : active les optimizations automatiques OPT o- : les desactive OPT w+ : active tous les warnings OPT w- : desactive tous les warnings OPT v+ : mode verbose OPT v- : mode abbrege OPT q+ : mode silencieux OPT q- : mode normal OPT a+ : alignement automatique OPT a- : alignement normal ( defaut ) - INCLUDE Insere le fichier a cet endroit du source et continue la procedure d'assemblage ( comme #include en C ) . Un source peut en include d'autres qui peuvent eux-memes en inclure d'autres qui peuvent... Il n'y a pas de limite de profondeur, mais un controle elementaire de references circulaires est realise. Le nom du fichier peut etre encadre de ' ou de " ( ou de rien du tout ) . - ONCE Comme #pragma once qui est implemente sur la plupart des compilateurs C. Inclue le fichier uniquement si il ne l'a pas deja ete auparavant. - INCBIN Voici LA commande qui manque cruellement sur TASM et MASM... Elle permet d'inclure un fichier binaire au milieu d'un code ... Plus besoin de galerer a faire des conversions hexa. Pour inserer la photo de votre copine a poil au label 'tut' il suffit desormais de faire : { Exemple : tut incbin cindy.jpg } ou { Exemple : tut incbin "cindy.jpg" c'est pareil... } - DC Inclue un octet, un mot, un mot long ou une chaine. { Exemple : dc.b 1,2,3,4,"Tototata",'t',10 dc.w $1234,"tuttut",4 } Dans ce cas, la chaine est inseree en tant qu'octets comme si on avait fait : { Exemple : dc.w $1234 dc.b "tuttut" dc.w 4 } - DS Inclue un certain nombre d'octets nuls. { Exemple : ds.b 4 equivaut a dc.b 0,0,0,0 ds.l 3 equivaut a dc.l 0,0,0 } - EVEN, ALIGN, SEGMENT, PAGE, DPAGE, PPAGE Insere des nops de facon a ce que ce qui suive soit aligne: EVEN = 2 octets ALIGN.B / .W / .L /.Q = Devinez (.Q = Quad) SEGMENT = 16 octets PAGE = 256 octets DPAGE = 512 octets PPAGE = 2048 octets - MIN ou MINI xxx Taille minimale de RAM necessaire au programme. Exprime en blocs de 16 octets. - LIMIT xxx ou MAX xxx Limite la taille maximale d'un .EXE a octets. Utile pour les programmes residents et les overlays. Exprime en blocs de 16 octets. - OVERLAY xxx Fixe l'overlay. - STACK Indique ou est placee la pile (SS:SP) au debut de l'execution d'un .EXE, ex: { Exemple: header * plein d'instructions prout stack * plein d'instructions } - HEADER Insere le header d'un fichier .EXE avec la table de relocation et tout le bordel. Generalement c'est toujours la premiere instruction d'un programme ... Mais bon on peut en mettre n'importe ou, on peut meme en mettre plusieurs (ca peut etre pratique pour des petits .EXE qui sont inclus dans un autre) ... IMPORTANT: La taille de ces header n'influe pas sur la taille logique d'un fichier. C'est logique mais bon pour les barges qui s'amusent a en mettre plusieurs et n'importe ou dans le source, ca peut etre utile. - ASSUME Permet de fixer la reference par rapport a laquelle sera calculee l'offset de tous les labels. TASM permet d'"assumer" une valeur differente par rapport a chaque descripteur de segment. Mouuuaaiiiiss... J'en vois pas trop l'utilite vu qu'on peut faire ce qu'on veut de nos pointeurs de segment a forciori mais je rajouterai peut-etre cette possbilite dans la prochaine version. - FATAL Arrete l'assemblage et vous ejecte. Ca ne sert absolument a rien (mais c'est rigolo...) - SECTION BSS ou simplement BSS Ce qui suit sera interprete pour calculer les offsets des labels contenus, mais pas integre dans le programme executable. - SECTION TEXT, SECTION DATA, TEXT ou DATA Annule l'effet des directives precedentes. - REAL ou REALMODE Indique que la taille de tous les segments qui vont suivre ( a partir de l'endroit ou se trouve cette directive ainsi qu'apres chaque SEGMENT, PAGE, DPAGE ou PPAGE ) est de 64Ko, comme c'est le cas par defaut en mode reel. Ces directives ne servent qu'a produire une erreur dans le cas ou l'on depasserait cette limite. Elles n'ont pas d'influence sur le code genere. - UNREAL ou UNLIMIT ou FLAT Contrairement aux directives precedentes, ce jeu de directives indique que le code qui suit est dans un segment de taille supposee infinie. Sous GEMA, tous les segments sont supposes avoir une taille infinie par defaut. - SEGSIZE Les segments qui suivent auront pour taille maximale . Ces trois ensembles de directives peuvent etre prefixees d'une directive d'alignement ( SEGMENT, PAGE, DPAGE, PPAGE ) ou servir elles-memes de prefixes a une instruction quelconque. Exemple : SEGMENT:REAL est equivalent a : SEGMENT REAL SEGSIZE 4096:PAGE est equivalent a : SEGSIZE 4096 PAGE Dans ces deux cas, l'ordre n'a absolument aucune importance. Ainsi DPAGE:UNREAL aura le meme effet que UNREAL:DPAGE . Ces directives ne sont generalement utiles qu'en mode reel ou protege avec des segments de tailles folkloriques. Dans tous les autres cas, elles sont inutiles, GEMA ne travaillant normalement qu'avec des segments infinis. III. Mnemoniques ________________ Toutes (a part deux) les mnemoniques de TASM peuvent etre utilisees telles quelles sous GEMA, y compris tous les synonymes (JZ et JE par exemple). Les instructions qui different sous TASM et MASM (exemple XLAT et XLATB) sont accessibles sous les deux formes par GEMA et ont bien entendu le meme effet. Mais il y a de nouveaux synonymes, qui sont pour la plupart les equivalents 680x0. Il y a aussi des formes plus logiques. La liste qui suit represente quelques instructions synonymes et celles qui necessitent un commentaire : LEAVE = UNLINK MOV = MOVE MOVSX = MOVESX MOVZX = MOVEZX TRAPV = INTO WBINVD = FLUSH TRAP = INT Tolere des absolus. Par exemple TRAP #14 est identique a TRAP 14 ou INT 14. RTED = RTID = IRETD RTE = RTI = IRET BRAF ~ JMPF JMPF est la version FAR de JMP. Il prend deux arguments qui sont respectivement le segment et l'offset, exemple JMPF $14c9,$418db2a. Mais comme on utilise bien souvent un Far Jump avec l'adresse d'un label ou une adresse absolue et qu'il est alors lourd de faire JMPF \label,:label , il vaut mieux utiliser BRAF qui est exactement comme JMPF en dehors du fait qu'elle ne prend qu'un seul argument qui est une adresse 32-bits qu'elle se debrouille pour convertir en segment et offset. Par exemple BRAF $12345 equivaut a JMPF $1234,5 Ces instructions peuvent etre utilisees en word ou en long (sur 386+ uniquement). BRA ~ JMP BRA est exactement comme JMP sauf qu'en toute logique, JMP label sous GEMA equivaut a un JMP [label] sous TASM, ce qui signifie un saut a l'adresse contenue dans label et non pas un saut a label.Toujours en toute logique, il conviendrait de faire JMP #label. Et c'est effectivement ce qu'il faut faire avec JMP. Mais etant donne qu'on fait beaucoup plus souvent des JMP #label que des JMP label, mieux vaut utiliser BRA qui est identique sauf dans ce mode d'adressage. BRA label equivaut a BRA #label ou JMP #label. En dehors de ce mode d'adressage, BRA peut prendre tous les arguments qu'encaisse un JMP, par exemple BRA (si,dx) . Un BRA ou un JMP peut etre suivi de .s ou .b s'il est court, ou de .l s'il doit s'effectuer en 32-bits (en mode protege uniquement sinon vous allez avoir des surprises a moins de defragmenter la Ram avant et de proteger un segment, par exemple via l'interface DPMI de QEMM... Mais c'est une autre histoire...) . REP = REPE = REPZ Les prefixes du type REP et les prefixes de segment CS DS etc... peuvent etre utilises de deux manieres : Soit independemment sur une ligne, ils sont alors consideres comme des instructions a part entiere. Soit en tant que prefixes qui doivent alors comme tout bon prefixe PRECEDER l'instruction. Ils doivent alors etre suivis de deux points (dans le cas precedent, pas de deux points, ca m'enerve de mettre des deux points alors qu'il n'y a rien derriere) { Exemple : toto ds gs:move.l (si),a rep : outs.b repne ins.l } Comme on peut le voir, on peut mettre des espaces a cote des deux points, comme d'habitude ca pose aucun probleme. HLT = STOP XOR = EOR CMC = NGC CLD = D+ ('+' comme : incremente) STD = D- ('-' comme : decremente) CLI = INTOFF STI = INTON (Les coders en Saturn apprecieront) ADDX = ADC BS+ = BSF (pareil, c'est plus clair de mettre + que (F)orward) BS- != BSR ATTENTION, BSR N'A PAS LE MEME SENS SOUS GEMA QUE SOUS TASM ET MASM En effet il est utilise pour appeller des sous-programmes comme nous le verrons plus bas par consequent pour scanner les bits a l'envers, il faut faire BS- imperativement. BTSTC = BTSTN = BTC BTSTR = BTR TAS = BTS = BTSTS BTST = BT (BSRF = JSRF) ~ CALLF C'est la version Far de Call. Le principe est le meme que pour JMPF et BRAF sauf que les instructions qui ne prennent qu'un argument sont BSRF et JSRF, l'instruction CALL FAR telle que nous la connaissions reste logiquement CALLF. C'est parfaitement ridicule de declarer les sous-programmes avec PROC NEAR ou FAR machin en assembleur. L'assembleur est fait pour ceux qui codent comme des porcs pour faire cracher les tripes de leur becanes et pas par des abrutis revant au PASCAL et au COBOL ou autres LOGO. Par consequent sous GEMA vous faites BSRF ou BSR suivant le type d'appel que vous voulez, au moins vous savez comment ca va etre assemble. (BSR = JSR) ~ CALL Version near de CALL. Memes remarques que pour les BRA et JMP. RTS = RTN RTSF = RTNF Retour d'un sous programme near ou far. Peuvent etre suivis d'un immediat. EXTA.Q = EXT.Q = CDQ EXTA = EXT ou EXT.W = CBW CWD = EXT.L = EXTA.L DIVS = IDIV DIVU = DIV LINK = ENTER WAIT = FWAIT (Microsoft/Borland) MULS = IMUL MULU = MUL INS, OUTS, MOVES, LODS et compagnie : Les instructions sur les strings doivent suivre la logique de GEMA, a savoir l'instruction suivie eventuellement de la taille, avec .W par defaut. Ainsi au lieu de OUTSD sous TASM, il suffit de faire OUTS.L. BHI = JNBE BCC = JAE = JNB = JNC BCS = JNAE BLS = JBE = JNA BGE = JGE = JNL BVC = JNO BLT = JNGE BLE = JLE = JNG BCXZ = JCXZ BEQ = JE = JZ BGT = JNLE BECXZ = JECXZ = JCEZ = BCEZ BPL = JNS BNE = JNE = JNZ BPO = JPO = JNP BVS = JO BPE = JPE = JP BMI = JS J'en ai peut-etre oublie, mais sont equivalentes : Toutes les equivalences reconnues par MASM et TASM Leurs equivalents Motorola. SETxx = Sxx C'est comme au dessus ... Par exemple SZ c'est identique a SEQ ... Tous les synonymes Microsoft, Borland et Motorola sont reconnus. LOOPE = LOOPZ = DBEQ LOOPNE = LOOPNZ = DBNE LOOP = DBF = DBRA ROXL = RCL ROXR = RCR SAHF = SAF ASL = SAL = SHL ASR = SAR ( != SHR ) SUBX = SBB XLAT = XLATB Evidemment quelque soit les synonymes choisis, les modes d'adressage gardent toujours la norme GEMA : Dans les cas ou un immediat est systematiquement attendu, on peut se permette de ne pas mettre de #, Lorsque la taille des registres depend de l'instruction (95% des cas) on peut utiliser des registres indetermines, Lorsqu'un argument source et un argument cible sont en jeu, ils doivent toujours etre dans cet ordre respectif. Les instructions qui possedent une variante 32-bits doivent etre activees par .L ou le sont automatiquement lorsqu'il s'agit d'immediats ou d'offsets constants 32-bits. Quoi qu'il en soit, lorsqu'il n'y a pas d'ambiguite possible, GEMA reconnait un certain nombre d'abus (comme le INT 14 qui devrait normalement n'accepter que INT #14), et dans tous les cas les solutions les plus logiques sont rentenues. En cas de probleme il y a tout plein de messages d'erreurs et de warnings assez precis. AAM et AAD Ces instructions peuvent etre suivies d'un nombre immediat (avec ou sans le #) et permettent une decomposition selon n'importe quel diviseur (et non pas seulement 10). Cela marche sur tous les processeurs actuels, mais n'est pas documente. SALC ICEBP = ICE01 = TRAP01 UMOV = UMOVE LOADALL Instructions non documentees des 386+. Voir www.x86.org pour plus d'informations. Tous ces opcodes sont implementes dans GEMA, mais un warning a lieu lorsque l'option verbose (-v ou --verbose) est activee. CMOV = CMOVE RDPMC UD UD2 Nouvelles instructions du P6, implementees dans GEMA. UD et UD2 semblant fonctionner sur tous les processeurs, ils ne generent jamais de warning. Voici un exemple de programme tres complexe et original puisqu'il affiche la phrase "Hello world !" ... { org $100 push cs pop ds ds = cs move #plouf,d offset de plouf dans dx move.b #9,ah 9 dans ah trap #$21 appel de l'exception $21 move #$4c00,a exit(0) trap #$21 et hop plouf dc.b "Hello world !",13,10,'$' le texte a afficher } Oh miracle quand on assemble ce petit bout de code on obtient un fichier COM qui affiche avec la fonte immonde du DOS un truc dans une langue etrangere... Voici une autre version beaucoup plus longue et sans interet. Mais elle contient la structure d'un programme executable complexe. La moitie des instructions est inutile pour afficher un texte, mais si vous attaquez des choses un peu plus serieuses elles vous semblera beaucoup plus interessante. { header cree un fichier .EXE et non un .COM overlay $1234 numero d'overlay (inutile) min 1+@fin memoire minimum necessaire (inutile) max 1+@fin ici pareil que la memoire maximum move cs,a adresse de segment code move a,ds ...dans ds move.b #9,ah fonction 9 move #plouf,d offset du label plouf dans DX trap #$21 appel de l'exception move #$4c00,a code de fin de programme DOS trap #$21 qu'on appelle plouf dc.b "Hello world !",13,10,'$' texte a afficher segment alignement a un multiple de 16 ds.l 128 128 mots longs d'espace pour la pile fin stack defini la nouvelle pile } Si malgre tout certaines choses vous semblent encore obscures n'hesitez pas a me contacter, la solution la plus rapide etant par E-Mail a l'adresse : j@nether.net IV. That's all folks J'espere que vous arriverez a utiliser ce fabuleux (n'ayons pas peur des mots) outil et que vous en verrez l'interet par rapport a TASM et MASM... Toutes vos suggestions, critiques, remarques et bug-reports seront les bienvenus... (Note du correcteur: Demandez lui encore et encore de completer sa doc au maximum, en lui foutant un paquet d'exemples etc etc ... -flemmard comme il est il ne le fera surement pas sinon- a vous de jouer ! Mogar Slayer Of Potatoes)