Sunteți pe pagina 1din 6

Petits exercices pour apprendre les bases

Dernière modification le 12/06/03

NB : Ces exercices ne sont que de petits exemples pour apprendre le langage.


Ils sont très simples et ils sont classés en fonction de leur forme et non de
leur thème ou de leur difficulté.

1°) Arithmétique signée/non signée

En arithmétique signée sur 16 bits, comment s'écrivent les nombres 199 et


-32768 (donner le résultat en complément à 2 et en notation hexa) ?

En arithmétique non signée sur 16 bits, comment s'écrivent les nombres 32768
et 65536 (donner le résultat en notation hexa) ?

2°) Procédures et macros

Ecrire une procédure qui parmi deux entiers (passés en paramètres sur la
pile) renvoie le plus grand dans AX.

Ecrire une procédure qui dit si un nombre positif (passé dans AX) est
premier.

Ecrire une macro qui écrit un entier à l'écran.

Ecrire une macro qui fait revenir le curseur de l’écran à la ligne

Ecrire une macro qui lit une chaîne de caractères au clavier.

3°) Programmes COM

Ecrire un programme COM qui affiche les noms des fichiers et dossiers du
répertoire courant.

Ecrire un programme COM qui écrit à l'écran les 20 premiers nombres premiers.

4°) Programmes EXE

Ecrire un programme EXE qui calcule la somme des n premiers entiers (n étant
une constante définie dans le programme avec DEF) et qui l'écrit à l'écran.
Faire une boucle (c’est-à-dire ne pas utiliser la formule de Pascal) !
Correction

NB : - Pour chaque exercice, il existe de très nombreuses façons de s’y


prendre. Nous n’en proposerons qu’une, sans nous soucier d’optimisation ni de
propreté « professionnelle » du code... Le seul but est que vous puissiez voir
si vous avez compris la logique du langage assembleur.
- Pour lire la correction, mettez la taille 10 !

1°) Arithmétique signée/non signée

→ En arithmétique signée sur 16 bits, comment s'écrivent les nombres 199


et -32768 (donner le résultat en complément à 2 et en notation hexa) ?

- Le nombre 199 s’écrit 16*12 + 7 ce qui donne en hexa C7 = 00C7

- Le nombre -32768 est l’opposé de +32768 qui s’écrit : 8*16^3, soit 8000 en hexa.
Inversons les bits : 0 va devenir F et 8 va se transformer en 7 (car 8h = 1000b et 0111b = 7h). Ca donne donc 7FFF.
Ajoutons une unité : ça fait 8000.

Petite question à 8000 balles : -32768 s’écrit donc 8000 en hexa, tout comme le nombre 32768 !! Où est donc le problème ? ? ?

Réponse à 32768 balles : on travaille ici sur 16 bits donc tous les nombres ne sont pas représentables ! On peut seulement coder
les entiers allant de –32768 à +32767. Si on cherche à dépasser ces limites du côté positif, on va se retrouver avec un nombre
négatif (et vice versa) ! Ici, 8000h code bien le nombre –32768 mais le nombre +32768 n’est pas représentable sur 16 bits.

→ En arithmétique non signée sur 16 bits, comment s'écrivent les nombres


32768 et 65536 (donner le résultat en notation hexa) ?

- Le nombre 32768 s’écrit 8000 (voir la question précédente). Remarque : ici nous sommes toujours sur 16 bits, mais en
arithmétique non signée. Les nombres représentables sont compris entre 0 et 65535.

- Le nombre 65536 n’est pas représentable sur 16 bits (car 65536 = 16^4 s’écrit en hexa : 10000 ce qui demande au moins 17
bits) !

2°) Procédures et macros

→ Procedure qui parmi deux entiers (passés en paramètres sur la pile)


renvoie le plus grand dans AX
comment *
Procédure qui renvoie le maximum de deux entiers SIGNES
Paramètres : sur la pile
Résultat : AX = maximum des deux nombres
*
max proc near
.386
pushf ;sauvegarde des flags
push bx bp ;sauvegarder BX et BP

mov bp, sp ;pour lire les paramètres


mov ax, word ptr ss:[bp + 8] ;lisons le deuxième paramètre
mov bx, word ptr ss:[bp + 10] ;et le premier
cmp ax, bx ;comparaison (soustraction)
jge MAXfini ;ax est-il plus grand (signé)
;NB : utilisez jae si vous voulez comparer des nombres non signés
mov ax, bx ;bx est le plus grand
MAXfini:

pop bp bx ;restauration de BP et BX
popf ;restauration des flags
ret 4 ;dépiler paramètres et retour
max endp

→ Procédure qui dit si un nombre positif (passé dans AX) est premier
comment *
Procédure qui dit si un nombre positif est premier
Paramètres : AX = nombre à tester
Résultat : AX = 1 si le nombre est premier et 0 sinon
*
test_prem proc near
.386
pushf ;sauvegarde des flags
pusha ;sauvegarde des reg. généraux
push ds ;sauvegarde de DS

cmp ax, 2 ;le nombre est-il < 2 ?


jb TPnon_premier ;oui ? alors pas premier !
je TPpremier ;si = 2 alors premier !

push cs ;mettre cs
pop ds ; dans ds
mov word ptr ds:[TPsto_nombre], ax ;stocker le nombre à tester
mov bx, 2 ;on va le diviser par 2
TPprochaine_div:
xor dx, dx ;mettre DX à 0 pour la division
div bx ;diviser DX:AX par BX
cmp dx, 0 ;pas de reste ?
je TPnon_premier ;non ? alors pas premier !
mov ax, TPsto_nombre ;restaurer le nombre dans AX
inc bx ;on va diviser par le suivant
cmp bx, ax ;si nouveau diviseur >= nombre
jae TPpremier ; alors le nombre est premier !
jmp TPprochaine_div ;sinon recommencer !

TPnon_premier:
pop ds ;restauration de DS
popa ;restauration des reg. généraux
popf ;restauration des flags
mov ax, 0 ;le nombre n'était pas premier
jmp TPfini

TPpremier:
pop ds ;restauration de DS
popa ;restauration des reg. généraux
popf ;restauration des flags
mov ax, 1 ;le nombre était premier ;-)

TPfini:
ret ;retour à l'appelant

;********** données ici **********


TPsto_nombre dw ? ;pour garder le nombre à tester
test_prem endp

→ Macro qui écrit un entier à l'écran


comment *
Macro qui écrit un entier à l'écran
Paramètres : AX = nombre à écrire
Résultat : écran...
*
ecrit_ent macro
local boucle1, boucle2, termine ;doit être la première ligne !
.386
pushf ;sauvegarde des flags
pusha ;sauvegarde des reg. généraux

mov dx, 0BEBEh ;empiler le mot BEBEh


push dx ; (comme repère)
mov bx, 10 ;on va diviser par 10

boucle1: ;pour trouver les chiffres


xor dx, dx ;mettre DX à 0 pour la division
div bx ;diviser !
push dx ;empiler un chiffre
or ax, ax ;a-t-on fini ?
jnz boucle1 ;boucler sinon !

boucle2: ;boucle pour l'affichage


pop ax ;obtenir un chiffre
cmp ax, 0BEBEh ;est-ce la fin ?
je termine ;oui ? alors quitter !
add al, '0' ;ajouter le code ASCII '0'
xchg al, dl ;mettre dans DL
mov ah, 02h ;écrire un caractère
int 21h ; à l'écran !
xchg dl, al ;restaurer DL
jmp boucle2 ;prochain chiffre
termine:

popa ;restauration des reg. généraux


popf ;restauration des flags
endm

→ Macro qui fait revenir le curseur de l’écran à la ligne


comment *
Macro qui fait revenir à la ligne
Paramètres : aucun
Résultat : écran...
*
ligne macro
fin_de_ligne equ 10 ;code ASCII 10 : LF
retour_chariot equ 13 ;code ASCII 13 : CR
push ax dx ;sauvegarder AX et DX

mov ah, 02h ;écrire un caractère


mov dl, fin_de_ligne ;caractère fin de ligne
int 21h ;zou !
mov dl, retour_chariot ;caractère retour chariot
int 21h ;zou !

pop dx ax ;restaurer AX et DX
endm

→ Macro qui lit une chaîne de caractères au clavier


comment *
Macro qui lit une chaîne de caractères au clavier
Paramètres : offset d'un buffer (par rapp. à DS) pour le résultat
Résultat : dans le buffer passé en paramètre
*
lit_chaine macro buffer?
push ax dx ;stocker ax et dx

mov ah, 0Ch ;la fonction 0Ch


mov al, 0Ah ; appellera la 0Ah
mov dx, buffer? ;adresse du buffer
int 21h ;zou !

pop dx ax ;restaurer dx et ax
endm

3°) Programmes COM

→ Programme COM qui écrit à l'écran les noms des fichiers et dossiers du
répertoire courant
comment *
Programme qui écrit à l'écran les noms des fichiers et des
dossiers du répertoire courant (sans les fichiers cachés,...)
Paramètres : aucun
Remarque : la macro ligne utilisée dans ce programme n’a pas été
réécrite. Il vous suffit de la copier-coller !
*
code segment use16
assume cs:code, ds:code, es:code, ss:code
org 100h
.386

dossiers equ 00010000b ;attributs normaux + dossiers

debut:
mov dx, offset masque ;masque de recherche
mov cx, dossiers ;attriburs de recherche

mov ah, 4eh ;pour trouver le premier


chercher:
int 21h ;c’est parti !
jc terminer ;si aucun fichier

taille_nom:
push cx dx ;sauvegarder attrib et masque
mov cx, 13 ;taille max + 1 du nom
xor al, al ;car. recherché : 00 terminal
mov di, 80h+1Eh ;départ (cf structure DTA)
repne scasb ;chercher le 00 terminal
sub cx, 12 ;déduire la
neg cx ; longueur du nom du fichier
mov bp, cx ; et la ranger dans bp

concat_$:
mov byte ptr [80h + 1Eh + bp], '$' ;ajouter le caract. ‘$’

ecrire_nom:
mov ah, 9h ;écrire une chaîne
mov dx, 80h + 1Eh ;offset de la chaîne
int 21h ;zou !
ligne ;revenir à la ligne

suivant:
pop dx cx ;restaure masque et attrib
mov ah, 4fh ;pour trouver suivant
jmp chercher ;allons-y !

terminer:
ret ;rendre la main au système

;********** données ici **********


masque db "*.*", 0 ;masque (rech.) + 0 terminal

code ends
end debut

→ Programme COM qui écrit à l'écran les 20 premiers nombres premiers


comment *
Programme qui écrit à l'écran les 20 premiers nombres premiers
Paramètres : aucun
Remarque : la macro ecrit_ent et la procédure test_prem utilisées
dans ce programme n’ont pas été réécrites. Il vous suffit de les
copier-coller !
*
title ecrit20prem
.386

code segment use16


assume cs:code, ds:code, es:code, ss:code
org 100h

combien equ 20 ;combien de premiers afficher ?


espace equ ‘ ‘ ;code ASCII de l’espace (32)

debut:
mov bx, 0 ;on teste à partir de 0
mov cx, combien ;nombre de nombres à afficher

prochain:
mov ax, bx ;nombre à tester dans AX
call test_prem ;est-il premier ?
cmp ax, 0 ;tester : si non premier
je vers_prochain ; alors passer au prochain
mov ax, bx ;sinon restaurer nombre
ecrit_ent ;écrire nombre

mov ah,02h ;écrire un caractère


mov dl, espace ;un espace
int 21h ;zou !

dec cx ;un de moins à écrire !

vers_prochain:
jcxz fini ;tester si CX = 0
inc bx ;pour tester le suivant
jmp prochain ;on va le tester, ce suivant !
fini:

ret ;on a fini

code ends
end debut

4°) Programmes EXE

→ Programme EXE qui calcule la somme des n premiers entiers et qui l’écrit
à l'écran
comment *
Programme qui écrit à l'écran la somme des n premiers entiers
naturels (n étant une constante).
Paramètres : aucun
Remarque : la macro ecrit_ent utilisée dans ce programme n’a pas
été réécrite. Il vous suffit de la copier-coller !
*
code segment use16
assume cs:code, ds:code, ss: pile
org 100h
.386

combien equ 20 ;somme de combien d’entiers ?

debut:
xor ax, ax ;accumulateur = 0
mov cx, combien ;pour le LOOP
cmp cx, 0 ;cas part. : somme de 0 entiers
je fin_boucle ;dans ce cas on sort
encore:
add ax, cx ;sinon on ajoute CX
loop encore ;et on LOOPe
fin_boucle:

ecrit_ent ;écrire le résultat


mov ah, 4ch ;pour quitter
int 21h ;quitter !
code ends

pile segment stack ;segment de pile


db 256 dup(?)
pile ends

end debut

S-ar putea să vă placă și