home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The Unsorted BBS Collection
/
thegreatunsorted.tar
/
thegreatunsorted
/
programming
/
asm_programming
/
GEMA_FRA.DOC
< prev
next >
Wrap
Text File
|
1995-12-06
|
37KB
|
1,030 lines
-(G)-(E)-(M)-(A)-
[G]enPC [E]lite [M]acro [A]ssembler
(C)oderite SECTOR ONE 1994-95
Documentation francaise de la version 2.5
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/dos-windows/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, 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
-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 <constante>...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 <constante>
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
- INCLUDE <fichier>
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 <fichier>
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 <xxx> 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 <Constante>
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 <taille>
Les segments qui suivent auront pour taille maximale <taille>.
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
WINBD = 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 (L'instruction SAL n'existe donc pas sur un 486 ! C'est du
pipeau !!!)
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)