Copy Link
Add to Bookmark
Report

Tutorial Assembleur - Chapitre 05

eZine's profile picture
Published in 
Tutorial Assembleur
 · 11 Oct 2020

  

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

Utilisations des sauts conditionnels avec CMP - Instructions mathématiques
--------------------------------------------------------------------------

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

Les sauts conditionnels sont souvent utilisés dans des boucles. Ces boucles vont nous s
ervir à exécuter 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 terminée.
Voici un petit exemple de code :

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

cette boucle n'est pas bien optimisée, 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'exécution du programme.
Si vous avez compris cela, vous avez à peu près tout compris des boucles. On peut bien entendu
remplacer le JNZ par un JNA ou une autre condition (voir tableau des conditions dans la leçon 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'expérience. :)

Les instructions mathématiques
------------------------------

MULTIPLICATION : MUL / IMUL

Je vais continuer avec d'autres instructions pour compléter et vous permettre d'effectuer
d'autres opérations. Pour l'instant, le cours est bien théorique mais attendez encore un peu...

Bon, commençons par la multiplication, très utile. L'assembleur utilise l'instruction MUL
pour les opérations non signées et IMUL pour les opérations signées. MUL nécessite une opérande
(un paramètre). Cette opérande 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 faîtes MUL BX, vous obtiendrez AX=10 et BX=5.

Pour IMUL, c'est pareil, les assembleurs acceptent de mettre des nombres négatifs dans un
registre (MOV AX,-10). Pour ce qui est des nombres négatifs, 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 négatif.
Donc pour 16 bits, les nombres signés iront de -32768 à 32767. IMUL s'utilise comme MUL sauf
qu'il faut indiquer que l'on travaille avec des nombres signés ou non-signés. C'est pourquoi,
il faut toujours effacer DX (mettre DX à 0) lors d'une multiplication non-signée.
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 résultats
erronés. De même, multiplier par DX donne de drôles de résultats.

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

Comme pour MUL et IMUL, nous avons DIV (nombres non signés) et IDIV (valeurs signées).
DIV divise la valeur de AX par le source. Comme pour IMUL et MUL, il faut que DX soit
correctement paramétré.

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 opérandes: 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 très 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 préferable d'utiliser MUL car une décomposition
en puissance de 2 prendrait plus de temps...

NEG
---

NEG demande une opérande : 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 problème en assembleur, est que nous ne pouvons utiliser les nombres à virgules
directement dans les registres (sauf avec un coprocesseur mais il demande
une programmation différente basée 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, redivisée pour retrouver un résultat 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 signés et les grands nombres, on arrive aisément à
des dépassements. Sachez aussi que plus vous utilisez un SHL ou SHR avec une opérande
grande, plus le résultat sera précis (plus de décimales 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 ###

← previous
next →
loading
sending ...
New to Neperos ? Sign Up for free
download Neperos App from Google Play
install Neperos as PWA

Let's discover also

Recent Articles

Recent Comments

Neperos cookies
This website uses cookies to store your preferences and improve the service. Cookies authorization will allow me and / or my partners to process personal data such as browsing behaviour.

By pressing OK you agree to the Terms of Service and acknowledge the Privacy Policy

By pressing REJECT you will be able to continue to use Neperos (like read articles or write comments) but some important cookies will not be set. This may affect certain features and functions of the platform.
OK
REJECT