-(G)-(E)-(M)-(A)- [G]enPC [E]lite [M]acro [A]ssembler (C)oderite

publicité
-(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
FranceTelecom 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 : [email protected]
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
l'instruction
que de la sous-entendre avec la
compris a la vie.
Car d'une part c'est plus
pas a vous
taper des WORD PTR et autres en
Ainsi :
sous TASM
plus complique de preciser la taille dans
taille des operandes, vous n'avez rien
clair comme ca, d'autre part vous n'avez
cas d'ambiguite.
NEG.L (SI,DI) sous GEMA equivaut a NEG DWORD PTR [SI+DI]
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 malheureusement 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
Tut
move.l a,b
addx (si,bx),c
ceci est un commentaire
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
Tata
move.l #Toto-Tata/2,Toto+2
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, contrairement 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
OPT
OPT
OPT
OPT
OPT
OPT
OPT
OPT
OPT
o+
ow+
wv+
vq+
qa+
a-
:
:
:
:
:
:
:
:
:
:
active les optimizations automatiques
les desactive
active tous les warnings
desactive tous les warnings
mode verbose
mode abbrege
mode silencieux
mode normal
alignement automatique
alignement normal ( defaut )
- 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
ds.l 3
equivaut a dc.b 0,0,0,0
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
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 BSimperativement.
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
BNE
BPO
BVS
BPE
BMI
=
=
=
=
=
=
JNS
JNE = JNZ
JPO = JNP
JO
JPE = JP
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
move #plouf,d
move.b #9,ah
trap #$21
move #$4c00,a
trap #$21
plouf
dc.b "Hello world !",13,10,'$'
ds = cs
offset de plouf dans dx
9 dans ah
appel de l'exception $21
exit(0)
et hop
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.
{
.COM
header
overlay $1234
min 1+@fin
(inutile)
max 1+@fin
plouf
pile
fin
cree un fichier .EXE et non un
numero d'overlay (inutile)
memoire minimum necessaire
ici pareil que la memoire maximum
move cs,a
move a,ds
move.b #9,ah
move #plouf,d
trap #$21
move #$4c00,a
trap #$21
dc.b "Hello world !",13,10,'$'
adresse de segment code
...dans ds
fonction 9
offset du label plouf dans DX
appel de l'exception
code de fin de programme DOS
qu'on appelle
texte a afficher
segment
ds.l 128
alignement a un multiple de 16
128 mots longs d'espace pour la
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 :
[email protected]
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)
Téléchargement