Il est de vous montrer que le codage en assembleur i386, d'une instruction arithmétique telle que la multiplication, est différent selon que l'on a affaire à des nombres entiers ou à des nombres flottants.
1h30
Les calculs sur les nombres entiers sont effectués par l'Unité Arithmétique et Logique du microprocesseur; ceux sur les nombres flottants par le coprocesseur arithmétique aussi appelé Unité de Calculs en Virgule Flottante. Par la suite nous verrons comment sont codées en langage d'assemblage certaines fonctions trigonométriques que vous pouvez utiliser dans vos programmes en langage C.
Saisiret compiler le programme C suivant, qui ne fait que multiplier successivement deux entiers puis deux flottants.
Le code assembleur généré ressemble alors à :
Segmenter ce programme, et indentifier les deux multiplications. Quelles instructions x86 sont utilisées ?
Le calcul de la fonction sinus se fait via l'appel d'une fonction C. En désassemblant la librairie mathématique, voici ce que l'on obtient :
080482b0 <__cos>: 80482b0: dd 44 24 04 fldl 0x4(%esp) 80482b4: d9 ff fcos 80482b6: df e0 fnstsw %ax 80482b8: a9 00 04 00 00 test $0x400,%eax 80482bd: 75 01 jne 80482c0 <__cos+0x10> 80482bf: c3 ret 80482c0: d9 eb fldpi 80482c2: d8 c0 fadd %st(0),%st 80482c4: d9 c9 fxch %st(1) 80482c6: d9 f5 fprem1 80482c8: df e0 fnstsw %ax 80482ca: a9 00 04 00 00 test $0x400,%eax 80482cf: 75 f5 jne 80482c6 <__cos+0x16> 80482d1: dd d9 fstp %st(1) 80482d3: d9 ff fcos 80482d5: c3 ret 80482d6: 90 nop 80482d7: 90 nop 80482d8: 90 nop 80482d9: 90 nop 80482da: 90 nop 80482db: 90 nop 80482dc: 90 nop 80482dd: 90 nop 80482de: 90 nop 80482df: 90 nop 080482e0 <__sin>: 80482e0: dd 44 24 04 fldl 0x4(%esp) 80482e4: d9 fe fsin 80482e6: df e0 fnstsw %ax 80482e8: a9 00 04 00 00 test $0x400,%eax 80482ed: 75 01 jne 80482f0 <__sin+0x10> 80482ef: c3 ret 80482f0: d9 eb fldpi 80482f2: d8 c0 fadd %st(0),%st 80482f4: d9 c9 fxch %st(1) 80482f6: d9 f5 fprem1 80482f8: df e0 fnstsw %ax 80482fa: a9 00 04 00 00 test $0x400,%eax 80482ff: 75 f5 jne 80482f6 <__sin+0x16> 8048301: dd d9 fstp %st(1) 8048303: d9 fe fsin 8048305: c3 ret 8048306: 90 nop 8048307: 90 nop 8048308: 90 nop 8048309: 90 nop 804830a: 90 nop 804830b: 90 nop 804830c: 90 nop 804830d: 90 nop 804830e: 90 nop 804830f: 90 nop 08048310 <__tan>: 8048310: dd 44 24 04 fldl 0x4(%esp) 8048314: d9 f2 fptan 8048316: df e0 fnstsw %ax 8048318: a9 00 04 00 00 test $0x400,%eax 804831d: 75 03 jne 8048322 <__tan+0x12> 804831f: dd d8 fstp %st(0) 8048321: c3 ret 8048322: d9 eb fldpi 8048324: d8 c0 fadd %st(0),%st 8048326: d9 c9 fxch %st(1) 8048328: d9 f5 fprem1 804832a: 9b df e0 fstsw %ax 804832d: a9 00 04 00 00 test $0x400,%eax 8048332: 75 f4 jne 8048328 <__tan+0x18> 8048334: dd d9 fstp %st(1) 8048336: d9 f2 fptan 8048338: dd d8 fstp %st(0) 804833a: c3 ret 804833b: 90 nop 804833c: 90 nop 804833d: 90 nop 804833e: 90 nop 804833f: 90 nop
Rappels : l'instruction fnstsw %ax
transfère le registre
d'état dans le registre AX. L'instruction fprem1
calcule le
reste de la dimision entière.
Expliquez le fonctionnement de ces fonctions, sachant que
l'instruction test $0x400
teste la valeur du bit 10, et que ce bit
correspond à Argument hors bornes
(voir manuel Intel vol.1,
pages 8-6 et 8-8).
Je vous propose d'écrire en assembleur (utilisant la FPU) un petit programme résolvant une équation du second degré. Bien entendu, la saisie et l'affichage des données peut être fait en langage C...