Copy Link
Add to Bookmark
Report
Tutorial Assembleur - Chapitre 06
TUTORIAL ASSEMBLEUR - chapitre 6
--------------------------------
La mémoire
----------
La mémoire et ses instructions
------------------------------
J'ai déjà écrit une introduction sur la mémoire de l'ordinateur dans la leçon 1, mais nous
allons aborder sa mise en place et voir d'une façon plus précise, la manière de l'utiliser.
Attention : nous travaillons pour l'instant en mode réel, le code protegé demande du code
différent.
Il existe pour cela plusieurs instructions. Nous avons vu que "MOV SI, offset MESSAGE" plaçait
dans SI, la valeur de l'offset de MESSAGE. Pour une donnée dans un autre segment, il faut
aussi utiliser le "MOV AX,seg MESSAGE" et ensuite "MOV DS,AX". En effet, les registres ES, DS,
FS et GS n'acceptent pas de valeur numérique directe mais seulement des registres.
Il existe une autre instruction, LEA, qui permet de placer l'offset dans un registre mais
en plus court. Par exemple "LEA SI,MESSAGE" placera dans SI, l'offset de Message.
Privilégiez l'emploi de LEA plutôt que du MOV. Cela rend le code plus clair et plus compact.
Pour pouvoir déplacer des blocs entiers de mémoire, nous n'allons pas lire chaque octet et
le placer dans l'autre bloc mais nous employerons les instructions :
MOVSB
MOVSW
MOVSD
La première pour déplacer une (B)ytes, la deuxième un (W)ord et la dernière pour déplacer
un (D)words qui font 32 bits.
Ces instructions demandent que la source (DS:SI) et l'arrivée (ES:DI) soient configurées.
Il ne faut pas diriger les données vers n'importe quel emplacement de la mémoire.
Vous planteriez à coup sur le programme. Nous verrons plus loin, comment allouer des blocs
de mémoire.
Par exemple dans DS:SI, nous pouvons avoir les données d'une image et dans ES:DI, l'adresse
de la mémoire video (A000h:0000). Si nous voulons copier 10000 bytes, nous employerons
directement le MOVSD (si nous travaillons avec un 386 ou plus) ou avec MOVSW.
Pour plusieurs MOVSx, il est inutile de faire une boucle. L'instruction REP est là pour cela.
Il faut utiliser conjointement avec REP, le registre CX qui contient le nombre
d'itérations (le nombre de fois que l'on répete le MOVSx).
Pour les 10000 bytes, nous avons :
MOV CX,10000
REP MOVSB
Si nous utilisons les Words (plus rapide), c'est :
MOV CX,5000 (un word=2 bytes)
REP MOVSW
Finalement, avec le 32 bits, c'est :
MOV ECX,2500 (un dword=2 words=4 bytes) - utilisation d'un registre étendu
REP MOVSD
A chaque MOVSx, DI augmente de 1,2 ou 4 bytes.
Maintenant, si nous voulons garder des données ou les placer dans un emplacement de la mémoire ?
Nous utiliserons les instructions :
STOSB
STOSW
STOSD
Comme pour les MOVSx, cette instruction stocke un byte, un word et un dword.
A la différence des déplacements, les STOSx utilisent AL, AX (EAX 32bits) comme valeur à
stocker. La valeur de AL,AX,EAX sera stockée dans ES:DI. A chaque STOSx, DI est
augmenté de 1,2 ou 4 bytes. Ces instructions sont utiles pour effacer l'écran par exemple
ou remplir un bloc mémoire avec la même valeur.
MOV CX,1000
MOV AX,0
REP STOSB
Dans cette exemple, CX équivaut à 1000, pour 1000 répétitions. Ensuite, le MOV AX,0 qui est
la valeur qui sera placée dans le bloc mémoire. Pour finir, le REP STOSB qui dit que nous
plaçons 10000 bytes de valeur 0 à l'emplacement de ES:DI. En fait, ici nous placons
AL, on ne tient pas compte de AH dans un STOSB.
Pour réserver de la mémoire, il faut employer les interruptions, ici nous restons
dans la mémoire conventionnelle, c'est à dire que l'on ne dépasse pas les 640ko attribués
par le DOS. Si l'on veut plus de mémoire, il faut utiliser les modes dits protégés ou
flat. La programmation de ces modes est différentes et il faut avoir quelques notions sur le DOS
et la gestion de la mémoire. Si vous voulez dès maintenant en savoir plus, lisez des
documentations comme celles d'Intel.
Pour la mémoire conventionnelle, on doit d'abord libérer l'emplacement occupé par notre
programme :
MOV BX,taille ; la taille=(taille du prog en octet / 16)+1
MOV AH,04ah
INT 21h
Ici, taille=4096 correspond 64ko. Ajustez donc la taille en fonction de votre programme.
J'ai ajouté 1 à la taille pour éviter des erreurs (normalement pas nécessaire, on ne
sait jamais ;).
Ensuite, il faut réserver le bloc de mémoire:
MOV AH,48h
MOV BX,mem_voulue ; (mem_voulue=memoire_desiree/16)+1))
INT 21h
JC NOT_ENOUGH_MEM
La mémoire voulue se calcule comme pour la libération de la mémoire. Le JC NOT_ENOUGH_MEMORY
est utile pour détecter les erreurs. Si la mémoire n'est pas disponible, votre programme
ira au label NOT_.... et fera ce que vous voulez pour indiquer l'erreur
(affichage d'un texte, retour au DOS). IMPORTANT, il faut conserver la valeur de
AX après avoir exécuté le INT 21h. AX contient le segment du bloc alloué et il
faut garder cette valeur pour pouvoir la réutiliser lors du désallouage.
Finalement, il faut désallouer les blocs de mémoire APRES les avoir utilisé (sinon quel intérêt ?).
MOV BX,4096 ; (taille du bloc)
MOV AX,segment_bloc ; (le segment du bloc, nous l'avons précieusement gardé)
MOV ES,AX
MOV AH,49h
INT 21h
Le fait de ne pas désallouer de la mémoire va vous en enlever pour des programmes qui
seraient exécutés par la suite.
### Chapitre 6 - dake / c a l o d o x ###
### http://www.space.ch/scene/calodox ###