Site optimisé pour fonctionner en 800x600
Click pour les stats...
|
Présentation-
BlitzListFr-
Téléchargement-
Cours ASM-
Liens-
Pourquoi un cours d'ASM ?
Vous vous demandez peut être pourquoi il y a un cours d'ASM (Assembleur) dans cette partie de mon site dédié au Blitz Basic.
C'est tout simplement parce que ça va vous servir si vous désirez programmer un jour des 'Libraries' (Bibliothèques de commandes pour le Blitz). J'ai eu
moi-même besoin de ce cours que Erwan Fouret m'a donner un jour ;-) Donc, essayez de vous y mettre un peu, et vous verrez qu'il est possible de
concevoir des codes qui vont accélérer grandement l'exécution de vos programmes en Blitz.
Sommaire
Les Bases de l'Assembleur
Pour bien comprendre l'assembleur, il est important de bien comprendre comment fonctionnent
l'héxadécimal et le binaire.
Les Nombres
- Le Binaire
Un chiffre binaire, ou bit ne peut avoir que 2 valeurs différentes (BInaire) : le 0 ou le 1.
Ceci est très pratique dans un composant électronique car 0 correspond à une absence de courant
et 1 au passage du courant.
En assembleur, on indique qu'un nombre est binaire en le faisant précéder du signe %.
Un nombre binaire de 8 chiffres est appelé octet.
Exemple : %10011101 est un octet.
La transformation d'un nombre binaire en nombre décimal se fait comme suit :
En partant de la droite du nombe binaire, on ajoute une puissance de 2 correspondant
à la position du chiffre si ce dernier est égal à 1.
Exemple : %1011 |
=(1*2^0)+(1*2^1)+(0*2^2)+(1*2^3) |
= 1 + 2 + 0 + 8 |
= 11 |
- L'héxadécimal
Un chiffre héxadécimal peut avoir 16 valeurs différentes (de 0 à F), on parle donc de base 16.
On utilise beaucoup l'héxadécimal car un chiffre héxadécimal correspond à un demi-octet,
c'est-à-dire à un nombre binaire de 4 chiffres.
On indique qu'un nombre est en héxadécimal en le faisant précéder d'un $.
Exemple : $B = %1011 = 11
La transformation d'un nombre héxadécimal en nombre décimal se fait comme suit :
En partant de la droite du nombe héxadécimal, on ajoute une puissance de 16 correspondant
à la position du chiffre et on la multiplie par l'équivalent décimal de ce chiffre.
Exemple : $90C3 |
=(3*16^0)+(12*16^1)+(0*16^2)+(9*16^3) ($C=12) |
= 3 + 192 + 0 + 36864 |
= 37059 |
Les Registres
Les registres sont des "petites cases" dans le microprocesseur lui-même. Il y a
essentiellement deux types de registres : les registres de données (de d0 à d7)
et les registres d'adresses (de a0 à a6, a7 étant le pointeur de pile, aussi appelé sp).
Tous ces registres sont en 32 bits, ils contiennent donc jusqu'à 4 octets.
Les registres de données ne contiennent que des données (comme le nom l'indique!).
Les registres d'adresses pointent sur une adresse en mémoire.
On peut ainsi obtenir l'adresse elle-même où le contenu de l'adresse, grâce à ces registres.
Le registre de pile a7 sert à sauvegarder des registres afin de les restaurer plus tard.
L'adressage et les instructions de base
Une des instructions de base est move. Elle permet de déplacer des valeurs,
des registres, etc. vers d'autres registres.
- Exemple 1:
(avec d0=$12345678 d1=$0000000)
move.l d0,d1
(on obtient d0=$13345678 d1=$12345678)
Le .l indique que l'instruction va se faire en mots longs (sur 32 bits).
- Exemple 2:
(avec d0=$12345678 d1=$00000000)
move.w d0,d1
(on obtient d0=$13345678 d1=$00005678)
Le .w indique que l'instruction va se faire en mots (sur 16 bits).
- Exemple 3:
(avec d0=$12345678 d1=$00000000)
move.b d0,d1
(on obtient d0=$13345678 d1=$00000078)
Le .b indique que l'instruction va se faire en octets (sur 8 bits).
- Exemple 4:
(avec d0=$00000000)
move.l #$123455678,d0
(on obtient d0=$13345678)
Le # indique que ce qui suit est une valeur et non une adresse.
- Exemple 5:
(avec d0=$00000000 et l'adresse $12345678 pointant sur la valeur $11112222)
move.l $12345678,d0
(on obtient d0=$111222 et non $12345678)
- Exemple 6:
(avec d0=$12345678)
moveq #0,d0
(on obtient d0=$00000000)
Le q indique que c'est une instruction rapide. La valeur à déplacer doit alors être comprise
entre -128 et 127.
- Exemple 7:
(avec a0=$00000000 et l'adresse $12345678 pointant sur la valeur $11112222)
movea.l $12345678,a0
(on obtient a0=$11112222)
Le a indique que l'on déplace une adresse vers un registre d'adresses.
Il peut être omis.
- Exemple 8:
(avec a0=$12345678 et l'adresse $12345678 pointant sur la valeur $11112222)
move.l (a0),d0
(on obtient d0=$11112222 et a0=$12345678)
Les parenthèses indiquent que l'on ne s'adresse pas au registre mais à son contenu.
Les parenthèses ne peuvent pas être utilisées sur les registres de données.
- Exemple 9:
(avec a0=$10000000 et l'adresse $10000000 pointant sur la valeur $11112222)
move.l (a0)+,d0
(on obtient d0=$11112222 a0=$10000004)
Le + indique que l'on incrémente le registre.
- Exemple 10:
(avec a0=$10000004 et l'adresse $10000004 pointant sur la valeur $11112222)
move.l -(a0),d0
(on obtient d0=$11112222 a0=$10000000)
Le - indique que l'on décrémente le registre.
- Exemple 11:
(avec a0=$10000000 et l'adresse $10000008 pointant sur la valeur $11112222)
move.l 8(a0),d0
(on obtient d0=$11112222 d1=$10000000)
Le fait de mettre un nombre avant les parenthèses permet d'ajouter ce nombre à l'adresse.
Une autre instruction de base est lea (Load Effective Address). Elle permet de charger le pointeur d'un label ou d'une variable
dans un registre d'adresse.
- Exemple 12:
(avec a0=$00000000)
lea dosname(pc),a0
dosname: dc.b "dos.library",0
(on obtient a0=dosname)
dc indique que l'on déclare une variable. C'est l'équivalent asm de Data en basic.
(pc) indique que l'on va chercher l'adresse à l'aide du registre pc
(Program Counter). Ceci permet d'accélerer les accès aux variables.
Opérateurs, Labels et Pile
Les Opérations de base
La soustraction se fait à l'aide de la fonction sub.
sub a,b est l'équivalent de b=b-a.
Exemple 1 avec d0=8 et d1=$A sub.l d0,d1 on obtient d0=8 et d1=2
Exemple 2 avec d0=$31 subq #1,d0 on obtient d0=$30
Le q indique que c'est une opérande rapide. La valeur à soustraire est alors comprise entre 1 et 8.
Exemple 3 avec d0=$10 et a0=$10000020 suba.l d0,a0 on obtient a0=$10000010
Multiplication et division
La multiplication s'effectue avec l'opérande mulu ou muls.
mulu effectue la multiplication sans tenir compte du signe,
muls tient compte du signe (le bit de signe est celui le plus à gauche de la variable).
mulu a,b est l'équivalent de b=b*a
Remarque : mulu.l et muls.l ne sont disponibles qu'à partir du 68020.
Exemple 1 avec d0=2 et d1=5 mulu d1,d0 on obtient d0=$A et d1=5
Exemple 2 avec d0=-2=$FFFFFFFE et d1=5 muls.l d1,d0 on obtient d0=$FFFFFFF6=-$A et d1=5
La division s'effectue avec l'opérande divu ou divs.
divu effectue la division sans tenir compte du signe,
divs tient compte du signe.
divu a,b est l'équivalent de b=b/a
Remarque : divu.l et divs.l ne sont disponibles qu'à partir du 68020.
Exemple 1 avec d0=$A et d1=2 divu d1,d0 on obtient d0=5 et d1=2
Exemple 2 avec d0=-$A=$FFFFFFF6 et d1=2 divs.l d1,d0 on obtient d0=$FFFFFFFE=-2 et d1=2
Les opérateurs logiques
Opérateurs booléens
Exemple 1 avec d0=$A=%1010 et d1=$E=%1110 or.b d1,d0 on obtient d0=%1110=$E et d1=$E
Tableau du OU (or) :
0 or 0 = 0
0 or 1 = 1
1 or 0 = 1
1 or 1 = 1
Exemple 2 avec d0=$A=%1010 et d1=6=%0110 and.b d1,d0 on obtient d0=%0010=2 et d1=6
Tableau du ET (and) :
0 and 0 = 0
0 and 1 = 0
1 and 0 = 0
1 and 1 = 1
Exemple 3 avec d0=$A=%1010 et d1=$E=%1110 eor.b d1,d0 on obtient d0=%0100=6 et d1=$E
Tableau du OU EXCLUSIF (xor ou eor) :
0 eor 0 = 0
0 eor 1 = 1
1 eor 0 = 1
1 eor 1 = 0
Quelle est l'utilité de ces fonctions ?
- or : permet d'ajouter des puissances de 2 sans retenues :
1 or 2=3.
2 or 4=6.
Il y a d'autres utilités plus subtiles que nous verrons en temps voulu.
- and : sert à masquer un registre :
$11223344 and $000000FF=$00000044
$11223344 and $FF00FF00=$11003300
- eor : sert notamment à faire 'cycler' un registre.
Par exemple, en bb2, pour faire du double-buffering, on fait varier la variable db entre 1 et 0 :
db=1-db.
On peut remplacer cela par : db=db eor 1
Tout comme and, eor peut servir à masquer un registre.
Autres opérateurs logiques
Exemple 1 avec d0=$12345678 lsl.b #8,d0 on obtient d0=$34567800
lsl effectue un décalage logique vers la gauche.
Ceci permet notamment de faire des multiplications très rapidement :
2 lsl 1=4
5 lsl 2=20
Exemple 2 avec d0=$12345678 lsr.l #8,d0 on obtient d0=$00123456
lsr effectue un décalage logique vers la droite.
Ceci permet notamment de faire des divisions très rapidement :
4 lsr 1=2
20 lsr 2=5
Exemple 3 avec d0=$12345678 rol.l #8,d0 on obtient d0=$34567812
rol effectue une rotation logique vers la gauche.
Exemple 4 avec d0=$12345678 ror.l #8,d0 on obtient d0=78123456
ror effectue une rotation logique vers la droite.
Les branchements et les labels
Exemple 1 : label1: bra label2 label2: bra label1
(Ce programme ne se terminera jamais)
L'instruction bra (BRanch Always) est l'équivalent de Goto en basic.
Exemple 2 : bsr label1 label1: rts
bsr est l'équivalent basic de Gosub.
rts est alors l'équivalent de Return.
En fait, rts (ReTurn from Subroutine) est aussi l'équivalent basic de End.
Tout programme asm doit finir par rts.
Remarques : rts est aussi l'équivalent asm de move.l (a7)+,pc
( cette dernière instruction n'est pas autorisée normalement)
'bsr label' est aussi l'équivalent asm de :
move.l pc,-(a7) bra label
La Pile
L'AmigaOS est un sytème multitâche. Chaque tâche doit donc, au moment où elle se termine, rendre le système
tel qu'elle l'a trouvée lors de sa création. Il faut donc, notamment, sauvegarder la valeur des registres
que l'on va modifier. Pour ce faire, on utilise la pile, dont le pointeur est stocké en a7.
Exemple 1
move.l a0,-(a7) | On sauvegarde a0 |
--- | Le... |
--- | Programme... |
move.l (a7)+,a0 | On restaure a0 |
rts | |
Note : On sauvegarde toujours un registre dans -(a7) et on le restaure toujours avec (a7)+.
Exemple 2
movem.l d0-d7/a0-a6,-(a7) | On sauvegarde tous les registres |
--- | Le... |
--- | Programme... |
movem.l (a7)+,d0-d7/a0-a6 | On restaure tous les registres |
rts | |
L'instruction movem déplace plusieurs registres vers un autre et vice-versa.
d0-d7 indique que tous les registres de d0 à d7 (inclus) sont pris en compte.
le signe / indique qu'il n'y a pas de lien entre le registre précédent et le suivant.
Exemple :
d0/d3 indique que seuls d0 et d3 sont pris en compte.
Tests, branchements, sauts
Les branchements conditionnels
Les Sauts
©1999 BadDolls
|