Document créé par P. TRAU, ULP-IPST, janvier 97. Pour toute remarque (y compris fautes de français), envoyez moi un
Vous pouvez ici accéder aux autres informations sur ce serveur, normalement ou par carte.
Autres URL sur l'assembleur (quand j'en trouve) :
http://members.nbci.com/_XMCM/winasm : Iczelion's Win32 Assembly Homepage,
www.programmersheaven.com : Programmers Heaven - Assembler Zone,
www.eskimo.com/~htak/win95asm : Windows 95 Assembly Language Programming,
www.citeweb.net/discase : PregraWeb - PrograZine. Regardez aussi cette page de liens : Microprocessor WWW Sites.
Si vous en connaissez d'autres,
.
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 ENDS
Les 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_v
autre 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
ENDM
On 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).
Vous pouvez ici accéder aux autres informations sur ce serveur, normalement ou par carte.