@Pierre Marchand, IFT Semaine 04 Programmation système
@Pierre Marchand, Plan de la rencontre Retour sur la semaine précédente Comparaison Branchements Structure de contrôle Chaînes de caractères et tableaux Instructions logiques Instructions arithmétiques
@Pierre Marchand, La semaine précédente Les modes d’adressages La gestion de la piles Le passage des arguments
@Pierre Marchand, Comparaison Lors d'une comparaison, par exemple cmp a,b, le processeur effectue la soustraction a – b et positionne les indicateurs selon le résultat de l'opération. Les indicateurs qui nous intéressent ici sont : ZF = zero flag = 1 si le résultat est nul, sinon ZF = 0, CF = carry flag = 1 si une retenue est générée, sinon CF = 0, SF = sign flag = 1 si le résultat est négatif, sinon SF = 0, OF = overflow flag = 1 s'il y a débordement de capacité, sinon OF = 0 On rappelle qu’un débordement de capacité a lieu si, lors d’une opération sur des opérandes de même signe, le résultat est de signe différent.
@Pierre Marchand, Effets des addition sur les flags Addition CasExempleSFZFOFCF 1.P + P = P = P+ P = N * = P+ N = P70 + F0 = P+ N = N = E N+ N = P *A = N+ N = NF0 + E0 = D01001
@Pierre Marchand, Effets des soustraction sur les flags Rappelons-nous que la comparaison est en fait une soustraction Cas ExempleSFZFOFCF 1.P - P = P = P - P = N = E P - N = P50 - F0 = P - N = N * = A N - P = P *B = N - P = NA = N - N = PC0 - A0 = N - N = NA0 - F0 = B01001
@Pierre Marchand, A > B (non signé) Exemple CasSFZFOFCF A > 0 et B > = 40P - P = P0000 A = 70N - P = P0010 A = 80N - P = N1000 A < 0 et B < = 10N - N = P0000 Contre exemple : A > 0 et B > = F0P - P = N1001 A > 0 et B > = 00P - P = P0100 A < 0 et B < = F0N - N = N1001 A < 0 et B < 0A0 - A0 = 00N - N = P0100 C’est-à-dire : ZF = 0 et CF = 0.
@Pierre Marchand, comparaisons non signés On peut dériver de la sorte les conditions suivantes pour des quantités non signées: a (above)ZF = 0 et CF = 0> ae (above or equal)CF = 0>= b (below) CF = 1< be (below or equal)CF = 1 ou ZF = 1<=
@Pierre Marchand, A > B (signé) Exemple CasSFZFOFCF A > 0 et B > 0: = 40P - P = P0000 A > 0 et B < 0: 50 - F0 = 60P - N = P0001 A > 0 et B < 0: = C0P - N = N1011 A < 0 et B < 0: F = 60N - N = P0000 Contre exemple: A > 0 et B > 0: = F0P - P = N0011 A > 0 et B > 0: = 00P - P = P0100 A 0: = 40N - P = P0011 A 0: F = B0N - P = N1000 A < 0 et B < 0: 90 - F0 = A0N - N = N1001 C’est-à-dire : ZF = 0 et SF = OF.
@Pierre Marchand, Comparaisons signés On peut de la même façon dériver les conditions suivantes pour les quantités signées : g (greater) ZF = 0 et SF = OF ge (greater or equal)SF = OF l (less)SF OF le (less or equal)ZF = 1 ou SF OF
@Pierre Marchand, Branchements inconditionnels call jmpjump ret, retn, retf, iretreturn (near, far), interrupt return
@Pierre Marchand, Branchements conditionnels simple jejump if equal: ZF = 1 jnejump if not equal:ZF = 0 jzjump if zero: ZF = 1 jnzjump if not zero:ZF = 0
@Pierre Marchand, Branchements conditionnels non signés jajump above (x > y non-signé )CF = 0 & ZF = 0 jnajump not above = jbe jaejump above or equal CF = 0 jnaejump not above or equal = jb jbjump below (x < y non-signé)CF = 1 jnbjump not below = jae jbejump below or equal CF = 1 | ZF = 1 jnbejump not below or equal = ja
@Pierre Marchand, Branchements conditionnels pures Sur les indicateurs eux mêmes jcjump if carry: CF = 1 jncjump if not carry: CF = 0 jojump if overflow: OF = 1 jnojump if not overflow: OF = 0 jpjump if parity: PF = 1 jnpjump if not parity: PF = 0 jpojump if parity odd: PF = 0 jsjump if sign: SF = 1 (negative) jnsjump if no sign: SF = 0
@Pierre Marchand, Branchements conditionnels signés jgjump greater (x > y signé)SF = OF & ZF = 0 jngjump not greaterSF != OF & ZF = 1 jgejump greater or equalSF = OF jngejump not greater or equal = jl jljump less (x < y signé)SF != OF jnljump not less = jge jlejump less or equalSF != OF jnlejump not less or equal = jg
@Pierre Marchand, Branchements sur compteur jcxzjump if cx = 0 jecxzjump if ecx = 0
@Pierre Marchand, Variables signés ou non signés Il faut bien prendre garde d'utiliser le bon branchement selon le type de données considéré. En C, les variables sont signées par défaut. Pour avoir des variables non signées, on utilise la déclaration unsigned. Exemples : unsigned char x;0 ≤ x ≤ 255 unsigned short y;0 ≤ y ≤ unsigned long z; 0 ≤ z ≤ char x;-128 ≤ x ≤ 127 short y; ≤ y ≤ long z; ≤ z ≤
@Pierre Marchand, Structure de contrôle if simple if complexe while for switch
@Pierre Marchand, if simple if ( a > b )if:cmpa,b {jngelse… }… elsejmpendif {else:…… }endif:… Démontré dans l’exemple 01 disponible sur le site
@Pierre Marchand, if complexe if ( ( a > b ) && ( c <= d ) ) {if:cmpa,b …jngendif …cmpc,d }jnleendif … endif: Démontré dans l’exemple 01
@Pierre Marchand, while while ( a > b ) {while:cmpa,b …jngendwhile… }… jmpwhile endwhile:… Démontré dans l’exemple 01
@Pierre Marchand, for for ( i = 1; i < 10; i ++ ) {for:movi, 1 …jmptest …next:…… }inci test:cmpi, 10 jlnext endfor:… Démontré dans l’exemple 01
@Pierre Marchand, Instructions de boucle LOOP/LOOPW/LOOPD Loop Boucle vers une étiquette. Décrémente ecx en mode 32 bits ou cx en mode 16 bits (sans affecter aucun indicateur). Si (e)cx est 0 après avoir été décrémenté, l’exécution continue à l’instruction suivante. On peut forcer un comptage sur cx avec loopw et sur ecx avec loopd. L’étiquette doit être à moins de -128 à octets de l’instruction loop. oszapc = oszapc loopétiquette8 Démontré dans l’exemple 01
@Pierre Marchand, Instructions de boucle avec condition LOOPcc/LOOPccW/LOOPccD Loop Conditionally Boucle vers une étiquette tant que la condition est remplie et que (e)cx n’est pas 0. Décrémente ecx en mode 32 bits ou cx en mode 16 bits (sans affecter aucun indicateur). Si (e)cx est 0 après avoir été décrémenté, l’exécution continue à l’instruction suivante. On peut forcer un comptage sur cx avec loopw et sur ecx avec loopd. L’étiquette doit être à moins de -128 à octets de l’instruc- tion loop. oszapc = oszapc loopeétiquette8 loopz(w)étiquette 8 loopne(d)étiquette 8 Démontré dans l’exemple 01
@Pierre Marchand, Remplacement des instructions de boucle On peut remplacer avantageusement loop par les instructions qu’elle remplace : dececx; ou dec cx0.5 jnzboucle~0.5 Idem pour loopcc :; pour simuler loopz …; comparaison ou test jnzfinBoucle dececx jnzboucle finBoucle : Dans ce dernier cas il y a une petite différence. Si on sort de la boucle parce que ecx est 0, alors ZF = 1, tandis qu’avec loopcc ZF=1 seulement si la condition testée est 0. Il faut donc modifier légèrement le code subséquent.
@Pierre Marchand, Chaînes de caractères Types de chaînes Chaîne C Toto‘T’, ‘o’, ‘t’, ‘o’, \0 Chaîne Pascal Toto\04, ‘T’, ‘o’, ‘t’, ‘o’
@Pierre Marchand, Chaînes et tableaux Intel appelle également « chaîne » des tableaux de short, de long et autres. Un tableau est défini comme suit en C : short Tableau[n];// Tableau de n short non initialisés short Tableau[ ] = { 0, 2, -3, 4, 20 };// Tableau de 5 shorts Pour accéder à un élément d’un tableau, il y a deux façons : x = Tableau[i]; ou, si short * p = Tableau; alors x = *(p + 2 * i);// * 2 parce que short = 2 octets
@Pierre Marchand, Adressage des chaînes et tableaux Pour accéder à un tableau en assembleur, on fait lea esi, Tableau; ou mov esi, offset Tableau Ensuite, on utilise l’adressage indexé : movebx, i movax, [esi+ebx*2] movx, ax
@Pierre Marchand, Comparaison des chaînes et tableaux CMPSBCompare String Byte CMPSWCompare String Word CMPSDCompare String DoubleWord Compare l’octet, le mot ou le double mot pointé par esi avec l’octet, le mot ou le double mot pointé par edi. Les pointeurs esi et edi sont avancés automatiquement de 1, 2, ou 4 selon qu’il s’agit d’un octet, d’un mot ou d’un double mot. Si l’indicateur de direction DF est 0, esi et edi sont incrémentés. S’il est 1, esi et edi sont décrémentés.
@Pierre Marchand, Répétition des instruction de chaîne Cette instruction est souvent précédée de l’instruction REP ou REPcc. REPNE (ou REPNZ) est utilisé pour trouver la première correspondance entre deux chaînes. REPE est utilisé pour trouver la première différence entre deux chaînes. Avant la comparaison, ecx doit contenir le nombre maximum d’éléments à comparer. oszapc = cmpsbyte ptr [esi] cmpsb repnecmpsw Attention, le résultat est l’inverse de cmp cmp fait dest - source cmps fait source - dest
@Pierre Marchand, Instructions rep REPRepeat String Répète une instruction de chaîne le nombre de fois indiqué dans ecx. oszapc = oszapc reprépéter tant que ecx ≠ 0 repe, repzrépéter tant que source = destination et ecx ≠ 0 repne, repnzrépéter tant que source ≠ destination et ecx ≠ 0
@Pierre Marchand, Autres instructions de chaînes SCAS/SCASB/SCASW/SCASDScan String Flags Dans le cas de SCAS, un opérande doit être fourni pour indiquer la taille des éléments à traiter. À la fin de l’instruction, edi pointe vers l’élément suivant. Si ecx = 0, edi pointe vers l’élément qui suit la dernière comparaison. L’indicateur ZF est affecté selon le résultat de la dernière comparaison et non selon la valeur de ecx. oszapc = ± ± ± ± ± ± scasword ptr [edi|4 repnescasb4 repescasw4
@Pierre Marchand, Charger une chaîne ou un tableaux LODS/LODSB/LODSW/LODSDLoad Acc. from String Charge l’accumulateur avec un élément d’une chaîne en mémoire. esi doit pointer vers l’élément source, même si un opérande est fourni. Pour chaque élément chargé, esi est ajusté selon la taille de l’opérande et l’indicateur de direction DF. esi est incrémenté si DF = 0 et décrémenté si DF = 1. oszapc = oszapc lodsword ptr [esi] lodsb lodsw lodsd Cette instruction ne peut pas être utilisée avec rep.
@Pierre Marchand, Écrire une chaînes en mémoire STOS/STOSB/STOSW/STOSDStore String Data Copie la valeur de AL, AX ou EAX dans un emplacement mémoire dont l'adresse est contenue dans EDI (ES:DI). Ensuite, EDI est ajusté selon la taille de l'élément transféré et l'état de l'indicateur de direction. EDI est incrémenté si DF avait été mis à 0 avec CLD ou décrémenté si DF avait été mis à 1 avec STD. Avec la forme STOS de l'instruction, un opérande doit être fourni pour indiquer la taille des éléments à copier. La dérogation de segment n'est pas permise. Lorsque l'une des formes STOSB (octets), STOSW (mots) ou STOSD (doubles mots) est utilisée, c'est le choix d'instruction qui détermine la taille des éléments de données à traiter et si l'élément provient de AL, AX ou EAX.
@Pierre Marchand, Écrire une chaîne (la suite) STOS/STOSB/STOSW/STOSDStore String Data STOS et ses variantes sont souvent utilisées avec le préfixe REP pour remplir une chaîne avec une même valeur. Avant d'utiliser l'instruction REP, ECX doit contenir la nombre d'itérations désiré. oszapc = oszapc stosword ptr [edi] stosb repstosw stosd
@Pierre Marchand, Déplacer une chaînes ou un tableaux MOVS/MOVSB/MOVSW/MOVSDMove String Data Déplace une chaîne de données d’une région de la mémoire à une autre. esi doit pointer vers la chaîne source et edi vers la chaîne destination. Pour chaque élément déplacé, edi et esi sont ajustés selon la taille des opérandes et le bit de direction DF. Dans le cas de movs, il faut fournir des opérandes pour indiquer la taille des éléments à traiter. Ces instructions sont habituellement utilisées avec le préfixe rep. oszapc = oszapc repmovsb1 movsword ptr [dest], word ptr [source]1
@Pierre Marchand, Exemple 02 L’exemple 02 contient différentes fonctions de traitement de chaînes de caractères et de tableaux démontrant l’utilisation des instruction que nous venons de voire.
@Pierre Marchand, switch switch ( i )switch: {case1:cmpi,1 case 1:…jnecase2… break;… case 2:… jmpendswitch … case2:cmpi,2 break; jnedefault default:…… }… jmpendswitch default:… endswitch:…
@Pierre Marchand, Optimisation des switch Dans les systèmes à base de menus, il arrive souvent qu’on ait un énoncé switch comme le suivant, où une fonction différente est exécutée suivant le choix que l’utilisateur fait dans un menu : switch (choix) { case 0:fonction1(choix); break; case 1: fonction2(choix); break; case 1:fonction3(choix); }
@Pierre Marchand, Tables de fonctions en C En C, on peut obtenir une meilleure performance, surtout si la liste est longue, à l’aide d’une table de pointeurs de fonctions : void (* mesFonctions [3] ) ( int ) = { fonction1, fonction2, fonction3 }; ou int (* mesFonctions [3] ) ( int ) = { fonction1, fonction2, fonction3 }; Ensuite, on peut appeler une de ces fonctions comme suit : (* mesFonctions [choix] ) ( param ); On saute directement à la bonne fonction sans avoir à parcourir le switch.
@Pierre Marchand, Tables de fonctions en assembleur Dans le contexte C, nous pouvons accéder à ces fonctions en assembleur comme suit : … leaeax, mesFonctions movecx, choix movebx, param pushebx call[eax+ecx*4]// * 4 car pointeur = 32 bits addesp, 4...
@Pierre Marchand, Exemple 03 L’exemple 03 montre différentes implantation d’un même « switch »
@Pierre Marchand, Move conditionnel CMOVCC La famille d’instructions cmovcc permet d’éviter les bran- chements dans des instructions C telles que : x = (a > b) ? 1 : -1; moveax,a movebx,b cmpeax, ebx moveax,1 movedx,-1 cmovleeax,edx// si a > b, eax contient 1 // sinon, eax contient -1
@Pierre Marchand, Move conditionnel (la suite) CMOVCC L’instruction cmovcc est disponible avec toutes les conditions booléennes usuelles : cmovgreg, reg cmovgreg, mem cmovgereg, reg cmovgereg, mem cmovlreg, reg cmovlreg, mem cmovlereg, reg cmovlereg, mem etc.
@Pierre Marchand, Instructions logiques
@Pierre Marchand, Instructions and – or - xor AND/OR/XORLogical AND/OR/XOR Effectue une opération logique bit par bit entre l’opérande source et l’opérande destination et enregistre le résultat dans la destina- tion. oszapc = 0± ±? ±0 andreg, reg0,5 ormem, reg xorreg, mem andreg, immed ormem, immed
@Pierre Marchand, Instruction not NOTOne ’s complement negation Effectue le complément logique (complément à 1) de chaque bit de la destination. oszapc = oszapc notreg0,5 notmem
@Pierre Marchand, Instruction test TESTTest Teste les bits indiqués d’un opérande et positionne les indica- teurs. L’un des opérandes contient la valeur à tester. L’autre contient un masque indiquant les bits à tester. L’instruction fait le AND de la source et de la destination. Les indicateurs sont modifiés en conséquence, mais la destination n’est pas changée. oszapc = 0 ± ± ? ± 0 testreg, reg0,5 testmem, reg testreg, mem testreg, immed testmem, immed
@Pierre Marchand, Instruction rol - ror ROL/RORRotate Effectue une rotation de l ’opérande destination vers la gauche ou vers la droite du nombre de bits spécifié dans l ’opérande source. Le dernier bit décalé va également dans CF. oszapc = ±szap ± ROL ROR rorreg, 1rolreg, 1 rorreg, CLrolreg, CL rormem, CLrolmem, CL rormem, immedrolmem, immed C C
@Pierre Marchand, Instructions rcl - rcr RCL/RCRRotate Effectue une rotation de l’opérande destination vers la gauche ou vers la droite du nombre de bits spécifié dans l’opérande source. Cette rotation inclut le bit CF, de sorte qu’une rotation sur 9 bits est effectuée sur un registre de 8 bits, sur 17 bits pour un registre de 16 bits ou sur 33 bits pour un registre de 32 bits. oszapc = ±szap ± C C
@Pierre Marchand, Instructions rcl – rcr (la suite) RCL/RCRRotate rclreg, 1 rcrmem, 1 rclmem, CL rcrreg, CL rclreg, immed rcrmem, immed
@Pierre Marchand, Instructions arithmétiques
@Pierre Marchand, Instruction add ADDAdd Additionne l’opérande source à l’opérande destination. oszapc = addreg, reg0,5 addmem, reg addreg, mem addreg, immed addmem, immed
@Pierre Marchand, Instruction adc ADCAdd with Carry Additionne l ’opérande source et la retenue (CF) à l’opérande destination. oszapc = adcreg, reg8 adcmem, reg adcreg, mem adcreg, immed6 adcmem, immed
@Pierre Marchand, Addition de précision L’exemple 04 démontre cette opération A 3 A 2 A 1 A 0 B 3 B 2 B 1 B 0 S 3 S 2 S 1 S 0 CF Poids faible Adresse basse Poids fort Adresse haute
@Pierre Marchand, Instruction sub SUBSubtract Soustrait l’opérande source de l’opérande destination et stocke le résultat dans l’opérande destination. oszapc = ± ± ± ± ± ± subreg, reg0,5 submem, reg subreg, mem subreg, immed submem, immed
@Pierre Marchand, Instructions sbb SBBSubtract with borrow Ajoute l’indicateur CF au second opérande puis soustrait cette valeur du premier opérande. Le résultat est placé dans le premier opérande. oszapc = sbbreg, reg8 sbbmem, reg sbbreg, mem sbbreg, immed6 sbbmem, immed
@Pierre Marchand, Multiplication Deux instructions : MUL pour la multiplication non signée IMUL pour la multiplication signée
@Pierre Marchand, Multiplication signé et non signé Exemple: Supposons que eax = 0x eax peut être interprété comme: (non signé) ou (signé) Si ebx = 0x , alors: mulebx eax = 0x edx = 0x La réponse est le nombre 0x , qui vaut
@Pierre Marchand, Multiplication signé et non signé (la suite) Multiplication signée et non signée Mais : imulebx eax = 0x edx= 0xFFFFFFFE et la réponse est le nombre $FFFFFFE , qui vaut Remarquez que dans les deux cas le double mot de poids faible est le même.
@Pierre Marchand, Instructions mul MULUnsigned Multiply Si l’opérande est de 32 bits, multiplie eax par l’opérande et place le résultat dans edx:eax. eax et l’opérande sont considérés comme des quantités non signées. Si l’opérande est de 16 bits, multiplie ax par l’opérande et place le résultat dans dx:ax. Si l’opérande est de 8 bits, multiplie al par l’opérande et place le résultat dans ax. Les indicateurs OF et CF sont positionnés si la partie de poids fort du résultat n’est pas nulle. oszapc = ±????± mulreg mulmem
@Pierre Marchand, Instructions imul IMULSigned Multiply Si l’opérande est de 32 bits, multiplie eax par l’opérande et place le résultat dans edx:eax. eax et l ’opérande sont considérés comme des quantités signées. Si l’opérande est de 16 bits, multiplie ax par l’opérande et place le résultat dans dx:ax. Si l’opérande est de 8 bits, multiplie al par l’opérande et place le résultat dans ax. Les indicateurs OF et CF sont positionnés si le produit est étendu en signe dans edx pour des opérandes de 32 bits, dans dx pour des opérandes de 16 bits, ou dans ah pour des opérandes de 8 bits. oszapc = ±????± imulreg14 imulmem 15-18
@Pierre Marchand, Intruction imul (la suite) IMUL Deux syntaxes supplémentaires depuis le Dans la version à deux opérandes, le registre destination est multiplié par l’opérande source et le résultat est placé dans le registre destination. Dans la version à trois opérandes, les deux derniers opérandes sont multipliés ensemble et le résultat est placé dans le registre destination. Les bits OF et CF sont positionnés si le produit n’entre pas dans la destination. imulreg, immed 14 imulreg, reg imulreg, mem imulreg, reg, immed imulreg, mem, immed
@Pierre Marchand, Grandeur des opérandes d’une multiplication Exemple Multiplication de deux nombres de 64 bits -> 128 bits 45 x XHXL YHYL
@Pierre Marchand, Multiplication de mots quadruples Composition du produit en additionnant les produits partiels de 64 bits Exemple : long A[ ] = {0xFFFFFFFF, 0xFFFFFFFF}; long B[ ] = {0xFFFFFFFF, 0xFFFFFFFF}; long Produit[ ] = {0, 0, 0, 0}; XL YL XL YH XH YL XH YH Produit de 128 bits =
@Pierre Marchand, Division Division signée et non signée Exemple: Supposons que eax = 0xFFFFFFF8 eax peut être interprété comme: (non signé) ou-8 10 (signé) Si ebx = 0x et edx = 0x , alors: divebx eax = 0x edx = 0x qui vaut , reste 2.
@Pierre Marchand, Division signé et non signé Division signée et non signée Mais si ebx = 0x et edx = 0xFFFFFFFF idivebx eax = 0xFFFFFFFE, edx = 0xFFFFFFFE qui vaut -2 10, reste -2. Par contre, si ebx = 0x et edx = 0xFFFFFFFF divebx débordement de capacité parce que le quotient est > 32 bits.
@Pierre Marchand, Division signé et non signé (la suite) Division signée et non signée Avant une division non signée, si le dividende dans eax est d’une longueur inférieure ou égale à 32 bits, il faut s’assurer que edx = 0. Avant une division signée, si le dividende est d’une longeur inférieure ou égale à 32 bits, il faut s’assurer que edx est 0 si eax est positif et 0xFFFFFFFF si eax est négatif. On peut effectuer ceci automatiquement avec l’instruction cdq, qui étend eax en signe sur 64 bits dans edx. moveax, -597 movebx, 3 cdq idivebx
@Pierre Marchand, Instruction div DIVDivide unsigned Si l’opérande est de 32 bits, divise eax par l’opérande et place le quotient dans eax et le reste dans edx. eax et l ’opérande sont considérés comme des quantités non signées. Si l’opérande est de 16 bits, divise dx:ax par l’opérande et place le quotient dans ax et le reste dans dx. Si l’opérande est de 8 bits, divise ax par l’opérande et place le quotient dans al et le reste dans ah. oszapc = ?????? divreg56-70 divmem
@Pierre Marchand, Instruction idiv IDIVSigned Divide Si l’opérande est de 32 bits, divise eax par l’opérande et place le quotient dans eax et le reste dans edx. Les deux opérandes sont considérés comme des nombres signés. Si l’opérande est de 16 bits, divise dx:ax par l’opérande et place le quotient dans ax et le reste dans dx. Si l’opérande est de 8 bits, divise ax par l’opérande et place le quotient dans al et le reste dans ah. oszapc = ?????? idivreg56-70 idivmem
@Pierre Marchand, Instructions sal - shl SALShift arithmetic left SHLShift logical left Décale les bits de l’opérande destination vers la gauche le nombre de fois spécifié par l’opérande source. L’opérande source peut être cl ou une constante de 8 bits. OF est affecté seulement lors de décalages d’un bit. Dans les autres cas, il est indéfini. oszapc =±±±?±± salreg, 1salreg, immed84 salmem,1salmem, immed8 salreg,CL salmem,CL 0 CF
@Pierre Marchand, Instruction shr SHRShift logical RIGHT Décale les bits de l’opérande destination vers la droite le nombre de fois spécifié par l’opérande source. L’opérande source peut être cl ou une constante de 8 bits. OF est affecté seulement lors de décalages d’un bit. Dans les autres cas, il est indéfini. oszapc =±±±?±± shrreg, 14 shrmem,1 shrreg,CL shrmem,CL shrreg, immed8 shrmem, immed8 CF 0
@Pierre Marchand, Instruction sar SARShift arithmetic right Décale les bits de l’opérande destination vers la droite le nombre de fois spécifié par l’opérande source. L’opérande source peut être cl ou une constante de 8 bits. Le bit décalé à droite est placé dans CF tandis que le bit de gauche garde sa valeur. oszapc =±±±?±± sarreg, 14 sarmem,1 sarreg,CL sarmem,CL sarreg, immed8 sar mem, immed8 CF
@Pierre Marchand, Instructions shld - shrd SHLD/SHRDDouble Precision Shift Décale les bits du deuxième opérande dans le premier opérande. Le nombre de bits à décaler est spécifié par le troisième opérande. SHLD décale le premier opérande de n bits vers la gauche. Les positions laissées vacantes sont remplies par les n bits les plus significatifs du deuxième opérande. SHRD décale le premier opérande de n bits vers la droite. Les positions laissées vacantes sont remplies par les n bits les moins significatifs du deuxième opérande.
@Pierre Marchand, Instructions shld – shrd (la suite) Le nombre de décalages peut être cl ou une constante de 8 bits. oszapc = ?±±? ±± shldreg, reg, immed8 shldreg, reg, CL shldmem, reg, immed8 shldmem, reg, CL
@Pierre Marchand, Division binaire Donc Quotient = 0101 et Reste = /
@Pierre Marchand, Division binaire (la suite) Division binaire Division ( / 111) sur 6 bits RQDécalage no Q = Q = Q = Q = Q = Q = Q =
@Pierre Marchand, Division binaire (la suite) Division Principe Pour plus de détails, voir le chapitre 1 du cours Structure Interne des ordinateurs. Initialement, R = 0 et Q = Dividende; D est le diviseur. On décale Q dans R un bit à la fois. Si R ≥ D, on effectue R = R - D et on passe 1 à droite du quotient, sinon on passe 0. On répète ceci autant de fois qu’il y a de bits dans le registre Q, par exemple, 16 ou 32 fois. RQ 1 si R ≥ D
@Pierre Marchand, Division binaire (la suite) Division Finalement, on décale Q une dernière fois à gauche. À la fin de l’opération, R contient le reste et Q le quotient. On peut effectuer cet algorithme sur des opérandes de plusieurs mots, par exemple Q = 64 bits et R = 64 bits, etc.
@Pierre Marchand, Division de précision Division Division 128 bits par 64 bits Pour effectuer cette opération, on a besoin des fonctionnalités suivantes (fonctions ou macros) : longShiftLeft(src, dwords, shifts) longCompare(dst, src, dwords) longSub(dst, src, dwords) R Q 1 si R ≥ D RR+4Q+8Q+12Q+4Q D DD+4
@Pierre Marchand, Instructions neg NEGNegate Remplace l’opérande par son complément à 2. En fait, NEG effectue l’opération 0 - opérande. Si l ’opérande est 0, CF = 0, sinon CF = 1. Si l ’opérande contient -128 pour 8 bits, -32,768 pour 16 bits ou - 2,147,483,648 pour 32 bits, alors sa valeur ne change pas, mais OF et CF deviennent 1. oszapc = ± ± ± ± ± ± negreg0,5 negmem