FAYOLLE Samuel
Groupe E. Informatique – Electronique.

Cahier de Tp d’Assembleur 8086

Licence 2, Semestre 4 ( 2006 )

TP 1 : Formatage & affichage en binaire et hexadécimal

Exercice 1).

Réalisation d'un programme qui affiche une valeur sur 16 bits en binaire :

Pour ceci, nous allons placer la valeur à afficher dans les registres bl et bh, nous allons ensuite établir un masque dans le registre dh (10000000 en binaire) de façon à étudier le bit de poids le plus faible de bl. On va alors utiliser un ET, et vérifier si le bit de poids fort est un '1' ou un '0'. Dans chacun des cas on affiche la valeur trouvée, puis on décale à gauche bh et on relance la boucle.
Ainsi, cette opération va se répéter huit fois pour convertir le nombre de départ sur 16 bits en binaire, et l'afficher au fur et à mesure.

CODE :

mov ax, 1003h  
mov bx, 0        
int 10h

mov bl,23h			; on place la valeur 23 en hexa dans bl
mov bh,bl			; et dans bh
mov dh,10000000b		; on établit le masque de départ dans le registre dh
mov cx,8			; on place 8 dans cx, pour que la boucle se répète 8 fois

boucle: mov bl,bh		; la première boucle	
            and bl,dh		; on fait un ET bit à bit entre la valeur de bl et le masque (dh)
            cmp bl,dh		; comparaison entre le résultat du ET, et le masque	
            jz affiche1		; ici on vérifie si le bit de poids faible de bl est un 1, dans ce cas on vas à l'étiquette affiche1 
            mov ah,2		; on met 2 dans ah pour que l'instruction int 21h écrive le contenu de dl dans la console
            mov dl,'0'		; affichage d'un '0'
            int 21h
            jmp dec			; si on n'a pas eu de saut auparavant, on saute à l'étiquette dec

aff1:
            mov ah,2		
            mov dl,'1'		; affichage d'un '1'
            int 21h

dec:
            shl bh,1			; décalage à gauche, on va maintenant étudier le bit suivant

loop boucle			; on décrémente cx, et on refait la boucle tant que cx>0
ret

Exercice 2).

De la même manière, nous allons réaliser un programme qui affiche une valeur au format hexadecimal.

D'abord, on place la valeur désirée dans bl. On met 2 dans le registre cx de manière à ce que la boucle se répète deux  fois. 
Ensuite on tente de voir si la valeur est un chiffre ou une lettre; pour cela, on fait un ET entre la valeur à afficher et le masque F0h qui vaut 11110000 en binaire, puis on décale à droite le résultat du ET (dans ah) de 4. Si ah est supérieur à 9 c'est donc un chiffre et sinon, (inférieur ou égal), c'est une lettre.
Pour afficher une lettre, on soustrait 10 de la valeur de bl, et on ajoute 41h au résutlat de cette soustraction (dans bl) pour le transfomer en lettre. Et enfin on l'affiche. 

CODE :

mov bl, 23h			; valeur que l'on veut afficher en binaire
mov ah, 23h
mov cx, 2			; la boucle va se répéter 2 fois
mov ah, 2 			; pour l'affichage
mov bh, F0h			; le masque (vaut 11110000 b)
          
boucle:  
	mov ah,bl 
        	and ah, bh 		; on va comparer bl avec le masque (de 4 en 4) 
    	shr ah,4			; décalage à droite de 4
        	cmp ah,9                      	; si on dépasse 9, c'est une lettre, sinon, un chiffre
       	jle  aff1			; si ah <= 9, on saute à aff1
                                
    	sub bl,10
    	add bl,41h                     ; transformation en lettre
    	int 21h
	jmp dec

aff1:
    	add dl,30h                     ; transformation en chiffre
    	int 21h
    
dec: 
   	shl bl,4    		; décalage à gauche de 4

loop boucle:
    
ret     

TP 2 : Opérations arithmétiques

Exercice 2).

Nous allons créer un programme qui calcule la valeur maximale d'un tableau de 10 éléments.

D'abord, on place la taille du tableau (tabsize) dans le registre cx afin de répéter la boucle le nombre de fois qu'il y a de valeurs dans le tableau. Au départ maxi et si valent 0, on teste la première valeur du tableau en mettant tab[si] dans al, puis en comparant al et maxi. Si al est supérieur à maxi, on met dans maxi la valeur de al, sinon, on incrémente si, cx est incrémenté et on recommence le test sur la suite des valeurs du tableau. Enfin, on affiche la valeur de maxi.

CODE :

mov ax, 1003h  
mov bx, 0        
int 10h

mov cx, tabsize			; on met la taille du tableau dans cx
mov si, 0  			; on met 0 dans le registre si

boucle:
	mov al, tab[si]		; al prend la valeur de tab[si]	
	cmp al, maxi		; on compare ah au maxi
	jl etiqu			; si al est inférieur on saute à etiqu
	mov al, tab[si]		; sinon, on remplace maxi par al, la valeur en cours
	mov adrmaxi, si
	mov maxi, al
etiqu:
	inc si			; on incrémente si, pour avancer dans le tableau

loop boucle

	mov ah, 2		; affichage !
	mov dl, maxi
	int 21h

tab db 10,5,3,2,1,0,78,5,12,10	; initialisations !!!
tabsize db 10
maxi db 0			; au départ, maxi vaut 0
adrmaxi db ?

Exercice 3).

Nous allons réaliser le code du calcul de la racine carré d'un nombre.

Pour commencer, le registre cx va permettre de stocker la valeur du cumul et bx celle du poids. Au départ le cumul vaut 128 et le poids 64. On met donc 80h dans cx, et 40h dans bx.
Au début, on met cx dans ax puis on effectue l'opération cx*ax pour obtenir cumul ² dans le registre ax. On compare ensuite ce résulat avec la valeur dont on désire trouver la racine carrée. Si ces deux valeurs sont les mêmes, alors on a terminé puisque la racine carré désirée est cumul ! Sinon, on va comparer cumul ² et la valeur à l'adresse 0000h, si cumul ² est supérieur alors on enlève le poids à cumul, si c'est inférieur, on ajoute le poids à cumul, et on remet le tout dans cumul.
Après ceci, il faut diviser le poids par 2; on va alors faire un décalage droite de bx (qui contient le poids) ce qui revient à diviser par 2 la valeur de bx, et met le résultat dans bx. On retourne au début de la boucle avec la nouvelle valeur du cumul tant qu'on ne saute pas à l'étiquette fin, ce qui signifirait que la racine carré a été trouvée.

CODE :

mov word ptr[0000h], 25
mov cx, 80h
mov bx, 40h

deb: mov ax, cx
       mul cx 			 ; on effectue l'opération 80h * 80h, et on met le résultat (cumul ²)  dans le registre ax
       cmp ax,[0000h] ; on compare si cumul ² est égal à la valeur qui se trouve à l'adresse 0000h (ici 25)			
       je fin:			 ; si c'est égal, on saute à l'étiquette fin
       
       cmp bx,0			 ; on compare si le poids vaut 0
       je fin:
     
       cmp ax,[0000h]		 ; on compare cumul ² et la valeur à l'adresse 0000h
       jg moins:			 ; si c'est supérieur, on saute à moins
       
       add cx, bx			 ; on augmente cumul, en ajoutant le poids à cumul
       jmp plus:
     
     moins: 
           sub cx,bx		 ; on diminue cumul
     plus: 
           shr bx, 1			 ; on fait un décalage à droite de bx (du poids)

 jmp deb:			 ; on retourne au début et on refait tout avec le nouveau cumul
     
     fin:
           ret

TP3 : Sous-programmes.

Exercice 1) _a):
Nous désirons écrire une fonction retournant la moyenne d’un tableau et dont les paramètres sont l’adresse de départ du tableau et le nombre d’éléments.

En langage assembleur, on appelle procédure un sous-programme qui permet d'effectuer un ensemble d'instructions par simple appel de la procédure. 
Ici on a créé une procédure nommée « premiere » dans laquelle les paramètres sont le nombre d’éléments du tableau et son adresse de départ. Avec l’instruction lea, on met l’offset de tab dans le registre si. On met ensuite la valeur 0 dans les registres bx, ch et al. Le compteur cx est initialisé au nombre d’élements pour que la boucle se répète autant de fois qu’il y a d’éléments dans le tableau à étudier.
Dans la boucle, On ajoute toutes les valeurs du tableau dans le registre al. Une fois sorti de la boucle, on met la valeur de al dans bl et le nombre d ‘éléments dans al, pour pouvoir diviser la somme totale par le nombre d’éléments.

C'est l'instruction CALL qui permet l'appel d'une procédure. Elle est suivie soit d'une adresse 16 bits, désignant la position du début de la procédure, ou bien du nom de la procédure (celui de l'étiquette qui précède le mot clé PROC). 

CODE :
mov ax, 1003h  
mov bx, 0        
int 10h

premiere proc
lea si,tab  		; avec lea on met l'offset de tab dans le registre si
mov bx,0		; on met 0 dans les registres bx, ch et al
mov cx,nbe		; le compteur cx prend comme valeur le nombre d'éléments du tableau
mov ch,0 
mov al,0

boucle:
            add al,[si+bx]	; on ajoute à al la valeur de "tab[bx]", on commence à la première valeur du 
            add bx,1  	; tableau, puis on se déplace grâce à bx qui est incrémenté (tant que cx>0)		
loop boucle

		mov bl,al
		mov al,nbe
		mov ah,0
		div bl  			  ; dans le registre bl il y a le diviseur, et dans ax la valeur
ret     
premiere endp

tab db 10,5,2,8,7,11,13,9,12
nbe db 00001001b

b) :

Nous allons faire une fonction qui élève au carré les valeurs d’un tableau dont l’adresse de départ ainsi que le nombre d’éléments sont les paramètres.

Il suffit de parcourir le tableau et de multiplier la valeur par elle-même et de la remettre dans le registre dl. Pour ceci, on met dans al la valeur de la case du tableau en cours, puis on la met dans dl. Ensuite en faisant mul dl, on obtiendra la valeur de al au carré.

CODE :
mov ax, 1003h  
mov bx, 0        
int 10h

seconde proc
mov cx,nbe		; on place le nombre d’éléments dans cx
mov ch,0		; on met ch à 0
lea si,tab		; grace a lea on place l’offset du tableau dans si
mov bx,0		; on met bx à 0

    boucle:
        mov al,[si+bx]	; à chaque passage de boucle on met la valeur située à l’offset[si+bx] dans al  
        mov ah,0
        mov dl,al
        mul dl		; on élève la valeur de al au carré
        mov [si+bx],al
        add bx,1
    loop boucle
    
ret
seconde endp		; fin de la procédure

tab db 10,5,2,8,7,11,13,9,12
nbe db 00001001b

Exercice 2) :

En utilisant les fonctions de l’exercice 1, on va réaliser une fonction qui permet le calcul de l’écart type d’un tableau.

Variance, (S2) = écart au carré moyen de valeurs par rapport à la moyenne
Écart-type (S) = Racine carrée de la variance
Il suffit d’utiliser les deux fonctions précédentes, et de faire une nouvelle fonction qui va calculer l’écart type en faisant la racine carrée de la variance. Dans l’exercice 3 du TP2, on a déja fait la fonction qui permet de calculer une racine carrée.

D’abord, on appelle premier ce qui implique qu’on retrouve la moyenne calculée dans le registre al. Ensuite on déplace la valeur de la moyenne dans ax, puis on calcul le carré de cette moyenne.
Lorsqu’on appelle la seconde procédure, on remplace toutes les valeurs du tableau par leurs carrés. On fait la moyenne des carrés qui se met trouve dans al, en appellant à nouveau premier, puisque le tableau contient maintenant les carrés !
Il n’y a plus qu’à faire le calcul de la racine carré grâce à trois.

call premier		;

mov ax,al		; on place la valeur du registre al dans ax (DANS al, IL Y A LA MOYENNE)
mul ax   		; le carre de la moyenne se retrouve dans al
mov dh,al		; on met ensuite la valeur de al dans dh

call seconde		; on remplace toutes les valeur du tableau par leurs carrés

call premier		; on fait la moyenne des carrés qui se met trouve dans al

sub al,dh 		; on fait al moins dh dans al
 
call  trois 			; on calcul maintenant la racine carré !	

jmp saut:		; on va afficher

premier proc
lea si,tab  		; on prend l'adresse (offset) du tableau que l'on met dans si
mov bx,0
mov cx,nbe
mov ch,0 
mov al,0

boucle:
        add ax,[si+bx]
        add bx,1
loop boucle

mov bl,nbe
mov ah,0
div bl
ret
premier endp   		 ; on garde la moyenne dans al

seconde proc
mov cx,nbe
mov ch,0
lea si,tab
mov bx,0

boucle:
        mov al,[si+bx]
        mov ah,0
        mov dl,al
        mul dl
        mov [si+bx],al
        add bx,1
loop boucle
    
ret
seconde endp 			;on va remplacer toutes les valeurs par leur carré

 
 
trois proc 			; calcul la racine carrée 
mov word ptr[0000h],al
mov cx, 80h
mov bx, 40h

deb: mov ax, cx
     mul cx  				;on met le resultat de cx² dans ax
     cmp ax,[0000h]
     je fin:
     
     cmp bx,0
     je fin:
     
     cmp ax,[0000h]
     jg moins:
     
     add cx, bx 			;ajoute bx au cumul
     jmp plus:
     
moins: 
     sub cx,bx 		        	;enlève bx au cumul
plus: 
     shr bx, 1 		        	;on fait un decalage a droite (division par 2)
     jmp deb:
     
fin: ret
trois endp 

 

 
saut:				; affichage / initialisations
 
; add your code here

mov dx, 0705h      ; print message using BIOS function at 7,5
mov bx, 0          ; page 0.
mov bl, 10011111b  ; white on blue.
mov cx, msg_size   ; number of characters to print.
mov al, 01b        ; update cursor only.
mov bp, offset msg
mov ah, 13h        ; BIOS function for print.
int 10h            ; print message at es:bp.

mov ah, 0          ; wait for any key....
int 10110b         ; same as int 16h or int 22.

ret   ; return to the operating system.

msg         db "press any key..."
msg_size =  $ - offset msg

tab db 1,5
nbe db 00000010b

END