Document créé par P. TRAU, en octobre 1988, et remis à jour en janvier 97. Eh oui, c'est bien vieux. Mais ce n'est pas complètement dépassé, je le garde. Pour toute remarque, ou proposition de mise à jour, envoyez moi un
Si vous êtes sous Linux, regardez le mini-howto assembleur
F E D C B A 9 8 7 6 5 4 3 2 1 0 +---------------------------------------------------------------+ | | | | | O | D | I | T | S | Z | | A | | P | | C | +---------------------------------------------------------------+Overflow (dépassement de capacité nb signé) / Decrémentation index/ Interruptions autorisées / Trap (pas à pas) / Signe négatif / Zéro / retenue Auxiliaire (entre le 4è et 5è bit) / nb Pair de 1 / Carry (retenue)
Mais on ne peut pas faire de transfert direct de mémoire à mémoireni d'adressage immédiat à destination d'un registre segment (passer par un registre général). La destination ne peut être un adressage immédiat.
Attention, en mémoire on stocke toujours l'octet de poids faible en premier. De même on stocke un offset avant un segment.
d destrination - s source
PA pas d'adresse à donner (registres fixés d'avance)
TA tous adressages (immédiat registre direct indirect-indexé)
RM adressage registre ou mémoire (direct indirect-indexé)
AF ne modifie aucun Flag MF modifie Flags O S Z A P C
MOV d,s : copie de la source dans la destination TA AF XCHG d,s : échange d,s (impossible sur segment) RM AF PUSH s : empilage (toujours 16 bits) RM AF POP d : dépilage RM AF XLAT : copie d=AL, s=[BX+AL] PA AF IN d,s : lecture port d=AL ou AX, s=ndeg. de port si<256 ou DX si entre 0 et 65535 AF OUT d,s : écriture port à partir de l'accumulateur AF LEA d,s : chargement d'un offset LEA BX,[DI+5]=MOV BX,DI ADD BX,5 cette instruction est surtout utile en MASM (LEA BX,truc[DI] TA AF LDS d,s : chargement double mot dans DS et d (d=registre général,s=TA) idem MOV d,s MOV AX,s[2] MOV DS,AX TA AF LES d,s : idem LDS mais avec ES PUSHF : empilage registre d'état PA AF POPF : dépilage flags (remet les flags dans l'état sauvé) PA MF LAHF : copie partie basse flags dans AH (compatible 8085) PA AF SAHF : copie AH dans partie basse du registre d'état PA MF
flags (sauf NOT) : S,Z,P suivant le résultat; O,C=0; A=?
NOT d : complément à 1 RM AF AND d,s : d := d ET s (ET bit à bit) TA MF OR d,s : OU TA MF XOR d,s : ou exclusif (un ou l'autre mais pas les deux) TA MF TEST d,s : nulle part := d ET s (sert aux tests) TA MF
ADD d,s : d:=d+s TA MF ADC d,s : d:=d+s+C (retenue opération précédente) TA MF INC d : d:=d+1 modifie tous flags sauf C (utiliser Z) TA MF AAA : ajustement ascii addition précédente dans AL PA MF masque les 4 bits hauts, si C=1 alors AH=01 sinon AH=00 modifie flags A et C; O S Z P=? DAA : ajustement DCB addition précédente (ne modifie pas AH) PA MF flag O=? SUB d,s : d:=d-s _ TA MF SBB d,s : d:=d-s-C TA MF DEC d : d:=d-1 (MF sauf C) TA MF NEG d : d:=-d (MF, C=1) TA MF AAS : ajustement ascii soustraction précédente (AL) TA MF MF mais seuls A et C significatifs DAS : ajustement DCB soustraction précédente (AL) O=? TA MF les ajustements ne marchent bien que sur des résultats positifs CMP d,s : nulle part:=d-s (sert aux tests) TA MF MUL s : AX:=AL*s ou DX|AX:=AX*s C=O=1 si partie haute <>0 RM MF les autres flags sont indéfinis IMUL s : idem sur entiers signés RM MF AAM ajustement ascii MUL précédent (AX uniquement) PA MF flags : seuls P,Z et S sont significatifs DIV s : (AL:=AX div s, AH:=reste) ou (AX:=DX|AX div s, DX:=reste) aucun flag n'est significatif RM MF IDIV s : idem entiers signés RM MF AAD ajustement ascii à faire juste AVANT DIV. AH doit valoir 0 flags : seuls P,Z et S sont significatifs PA MF
CBW : convertit l'entier signé dans AL en mot dans AX PA AF CWD : " " " " AX en double mot DX|AX PA AF Ces conversions sont souvent utilisées avant IDIV
Flags : O si changement de signe, C, les autres non modifiés sauf pour SAR
+----+ +------------------------------+ SHL/SAL | CF |<----| |<----- 0 +----+ +------------------------------+ +------------------------------+ +----+ SHR 0 ----->| |---->| CF | +------------------------------+ +----+ +------------------------------+ +----+ SAR +-->| |---->| CF | | +------------------------------+ +----+ +-----+ +----+ +------------------------------+ ROL | CF |<----| |<--+ +----+ | +------------------------------+ | +-------------------------------------+ +------------------------------+ +----+ ROR +-->| |---->| CF | | +------------------------------+ | +----+ +-------------------------------------+ +----+ +------------------------------+ RCL | CF |<----| |<--+ +----+ +------------------------------+ | +------------------------------------------+ +------------------------------+ +----+ RCR +-->| |---->| CF | | +------------------------------+ +----+ +------------------------------------------+
Ces opérations sont généralement précédées d'un préfixe de type REP, CX contenant le nombre d'itérations (boucle FOR pour REP, REPEAT pour REPZ REPNZ).
MOVSB/MOVSW : déplacement PA AF STOSB/STOSW : copie de AL ou AX dans le bloc destination PA AF LODSB/LODSW : copie source dans AL ou AX (avec LOOP par ex) PA AF CMPSB/CMPSW : comparaison PA MF SCASB/SCASW : comparaison destination, AL ou AX (recherche) PA MFen MASM on peut écrire MOVS dest,source, il choisira B ou W suivant le type de variable et mettra si nécessaire un préfixe de segment pour la source.
JMP adresse : saut inconditionnel.
L'adresse peut être donnée soit :
Sauts conditionnels (uniquement saut court -128 +127 octets) :
RET n : retour de sous programme. N représente le nombre d'octets à dépiler après l'adresse de retour (nombre PAIR, 0 par défaut). Sous DEBUG, utiliser RETF pour un call far (MASM le fait automatiquement).
INT n : appel d'interruption logicielle (sous-programmes du DOS par ex). N entre 0 et 255. Cet appel sauve en plus de l'adresse de retour (FAR) le registre d'état. Les flags T et I sont mis à 0 (masque interruptions et debug).
INTO : appel de INT 4 uniquement si flag O=1
IRET : retour d'interruption (avec récupération registre d'état).
modifications registre d'état (PA) : _ STC : C:=1 CLC : C:=0 CMC : C:=C STD : D:=1 (décrémentation) CLD : D:=0 (incrémentation) STI : I:=1 (autorise les interruptions) CLI : I:=0 (masquage)
On les obtient en mettant le numéro de fonction dans AH et appeler INT 21h.
Tout ce qui suit un ; est considéré comme commentaire
nom SEGMENT options ......... nom ENDSLes options peuvent être entre autre PUBLIC STACK ou AT valeur_segment. Un .COM ne peut avoir qu'un seul segment. Un .EXE doit avoir un segment STACK, il sera automatiquement mis dans SS à l'éxécution
ex: message DB 'ceci est un message pour la Fdeg. 09',10,13,'$' tableau DW 100h DUP(?)MOV AX,variable sera assemblé en MOV AX,[adresse]. Pour utiliser l'adresse d'une variable utiliser OFFSET (MOV BX,OFFSET variable pour utiliser ensuite un adressage indexé)
MASM mettra automatiquement les préfixes de segments, à
condition de lui dire ce qu'il y a dans les registres segments par ASSUME :
Attention, cette directive ne met pas de valeurs dans les registres, il faut les mettre (MOV AX,donnees mov DS,AX). Si la bonne valeur n'est pas dans le registre, il se passera n'importe quoi. Un préfixe de segment ne sera mis automatiquement que si la variable a déjà été déclarée avant. Sinon il suppose que la variable sera dans le segment par défaut (ou celui précisé), et donnera une erreur si elle n'y est pas.
Nouveau_type= BYTE WORD DWORD NEAR FAR...
ex : offset_v DW 1234 segment_v DW 5678 LDS BX,DWORD PTR offset_vautre solution :
adresse_v LABEL DWORD offset_v DW 1234 segment_v DW 5678 LDS BX,adresse_vLABEL donne l'adresse actuelle et un type à une variable, sans prendre de place.
;fichier PROC.ASM ;fichier PRINC.ASM code_proc SEGMENT code SEGMENT PUBLIC add ASSUME CS:code add PROC FAR EXTERN add:FAR ADD AX,BX debut: mov ax,100h RET ;automatiquement FAR mov bx,234h add ENDP call add code_proc ENDS code ENDS END ;ne rien rajouter, ce n'est END debut ;1ère instruction du ;pas le programme principal ;programme principal on apelle MASM proc; MASM princ; LINK princ+proc,proc;
nom MACRO parametres_formels ...... ENDM ;; ne pas redonner ici le nom, ça ferait récursivitéLes paramètres seront recopiés tels quels (idem EQU). On peut déclarer LOCAL label pour que le label soit local : un autre nom est donné à chaque appel.
ex : zero MACRO var,nb LOCAL boucle ;;pas de commentaire entre MACRO et LOCAL! mov DI,nb inc DI ;;REP STOS VAR serait mieux mais boucle:mov var[DI],0 ;;n'utilise pas LOCAL dec DI jz boucle ENDMOn peut l'appeler par ZERO tableau,AX ou ZERO tableau,16
Rq : on peut regrouper des macros courantes dans un fichier appelé par :
INCLUDE nom_de_fichier
exemple : code SEGMENT assume CS:code ORG 100h debut: ...... ...... code ENDS END debut ; debut DOIT valoir 100hà l'initialisation, CS est mis au premier endroit libre. DS, ES, SS sont normalement mis égaux à CS (suivant la version du DOS).
P. TRAU, ULP, janvier 97