TUTORIAL ASSEMBLEUR - chapitre 5
--------------------------------

Utilisations des sauts conditionnels avec CMP - Instructions mathmatiques
--------------------------------------------------------------------------

Utilisations des sauts conditionnels avec CMP
---------------------------------------------

Les sauts conditionnels sont souvent utiliss dans des boucles. Ces boucles vont nous s
ervir  excuter des actions plusieurs fois de suite. La boucle se divise en deux 
parties : la partie qui fait l'action et la partie qui teste si l'action est termine. 
Voici un petit exemple de code :

MOV AX,0 (nous verrons plus tard que XOR AX,AX est plus petit pour le mme resultat)
Boucle:
INC AX
CMP AX,12
JE Fin
JMP Boucle
Fin:

cette boucle n'est pas bien optimise, nous pouvons faire mieux :

MOV AX,0 
Boucle:
INC AX
CMP AX,12
JNE Boucle

Nous avons enlev 2 instructions de saut, ici, le JNE (jump if not equal - saute s'il n'est
pas gal ) va effectuer le saut tant que AX n'est pas gal  12, des que AX=12, il va
stopper de faire la boucle et va faire poursuivre l'excution du programme.
Si vous avez compris cela, vous avez  peu prs tout compris des boucles. On peut bien entendu 
remplacer le JNZ par un JNA ou une autre condition (voir tableau des conditions dans la leon 4).
On peut aussi mettre plusieurs CMP dans une boucle ou faire plusieurs boucles dans une
grande boucle. C'est facile mais a vient aussi avec l'exprience. :)

Les instructions mathmatiques
------------------------------

MULTIPLICATION : MUL / IMUL

Je vais continuer avec d'autres instructions pour complter et vous permettre d'effectuer 
d'autres oprations. Pour l'instant, le cours est bien thorique mais attendez encore un peu...

Bon, commenons par la multiplication, trs utile. L'assembleur utilise l'instruction MUL 
pour les oprations non signes et IMUL pour les oprations signes. MUL ncessite une oprande 
(un paramtre). Cette oprande s'appelle la source. Le nombre qui doit tre multipli se 
trouve OBLIGATOIREMENT dans AX. La source est un registre (BX,CX). Si vous 
avez AX=2 et BX=5 et que vous fates MUL BX, vous obtiendrez AX=10 et BX=5.

Pour IMUL, c'est pareil, les assembleurs acceptent de mettre des nombres ngatifs dans un 
registre (MOV AX,-10). Pour ce qui est des nombres ngatifs, sur 16 bits par exemple, 
-10 sera comme 65525 (65535-10). Le processeur soustrait  la valeur limite du 
registre (ici 16 bits= 65535), la valeur absolue du nombre ngatif. 
Donc pour 16 bits, les nombres signs iront de -32768  32767. IMUL s'utilise comme MUL sauf
qu'il faut indiquer que l'on travaille avec des nombres signs ou non-signs. C'est pourquoi, 
il faut toujours effacer DX (mettre DX  0) lors d'une multiplication non-signe. 
Dans le cas d'un IMUL, il faut utiliser l'instruction CWD (convert word to doubleword), qui
'tend' le signe de AX dans DX. Omettre ces instructions peut conduire  des rsultats
errons. De mme, multiplier par DX donne de drles de rsultats.

DIVISION : DIV / IDIV
---------------------

Comme pour MUL et IMUL, nous avons DIV (nombres non signs) et IDIV (valeurs signes). 
DIV divise la valeur de AX par le source. Comme pour IMUL et MUL, il faut que DX soit
correctement paramtr. 

Donc si nous avons AX=12 et BX=5, ensuite IDIV BX, nous aurons AX=2 et DX=2 (DX est le reste). 

N'oublier pas qu'on ne peut pas diviser par 0 !!! Si vous passez outre, le programme retourne
au DOS et affiche 'Div by 0'.

SHR et SHL
----------

SHR permet de diviser plus rapidement les registres. SHR demande deux oprandes: le nombre 
 diviser et le diviseur. SHR divise par une puissance de deux. 
Pour diviser par deux AX,BX,CX ou DX (et les autres registres aussi), on met 
SHR AX,1 (1 parce que 2^1=2), si on veut diviser BX par 4, on fait 
SHR BX,2 (2 car 2^2=4), SHR CX,3 (2^3=8) divise CX par 8. Compris ? C'est trs rapide,
pour diviser AX par 256, on aura SHR AX,8.  SHL, c'est pareil sauf qu'on 
multiplie : SHL AX,4 (2^4=16) multiplie AX par 16. On peut combiner aussi des SHL pour multiplier
par une valeur qui n'est pas une puissance de 2.

Si nous voulons multiplier AX par 320, on remarque que X*320 = X*256+X*64,
or 64 et 256 sont des puissances de 2, donc nous allons multiplier par 256
et multiplier par 64, et additionner les 2 resultats :

MOV AX,12  ;on veut multiplier 12 (=X)
MOV BX,AX  ;on copie dans BX (AX=X ; BX=X)
SHL AX,8   ;on multiplie par 256 (AX=X*256)
SHL BX,6   ;on multiplie par 64 (BX=X*64)
ADD AX,BX  ;on additionne dans AX (AX=X*256 + BX) -> (AX=X*256+X*64=X*320) 

et voila. cependant dans certains cas, il est prferable d'utiliser MUL car une dcomposition
en puissance de 2 prendrait plus de temps...

NEG
---

NEG demande une oprande : la destination. Il change le signe de la destination. 
Par exemple si AX=12, alors NEG AX donnera AX=-12. Si CL=-3 
alors NEG CL changera la valeur de CL en 3. Simple non ?. 

Les nombres  virgules
----------------------

Le problme en assembleur, est que nous ne pouvons utiliser les nombres  virgules 
directement dans les registres (sauf avec un coprocesseur mais il demande
une programmation diffrente base sur une pile). Nous utiliserons les nombres 
 virgule fixe. Il s'agit simplement d'effectuer des calculs avec des valeurs assez grandes
qui seront ensuite, redivise pour retrouver un rsultat dans un certain intervalle.
Nous voudrions avoir 0.5 dans AX, mais AX n'accepte pas de nombre  virgule, nous allons
simplement multiplier AX par 256, or 256*0.5=128, parfait, c'est un nombre entier :

MOV AX,128

maintenant, nous allons multiplier 300 par 0.5 (donc par 128)

MOV CX,300
XOR DX,DX  ;comme MOV DX,0
MUL CX

dans AX, nous avons (300*128), mais ce nombre est 256x trop grand ! il suffit de le
rediviser (qui est en fait un simple decalage peu couteux en temps de calcul) :

SHR AX,8 

Nous avons dans AX = (300*128)/256 = 150. Et voila ! nous avons effectu une MUL avec 
un nombre  virgule fixe mais seulement en utilisant des entiers. Cependant, il convient
d'tre prudent avec les nombres signs et les grands nombres, on arrive aisment 
des dpassements. Sachez aussi que plus vous utilisez un SHL ou SHR avec une oprande
grande, plus le rsultat sera prcis (plus de dcimales disponibles). On aurait pu fort
bien faire :

MOV AX,64 ;(0.5*128)
MOV CX,3200
XOR DX,DX
MUL CX
SHR AX,7  ;AX/128

Nous avons simplement une virgule fixe '128x plus grande'.

### Chapitre 5 - dake / c a l o d o x ###
### http://www.space.ch/scene/calodox ###
   
