la division est lente par rapport a la multiplication.
On va chercher a définir ce qu'est l'inverse d'un nombre pour le processeur.
Ce nombre est aussi appelé nombre magique.
Source / Exemple :
.NOLIST
;------ emplacement des déclarations
.486
.model flat, stdcall
option casemap :none ; case sensitive
include windows.inc ;
include kernel32.inc
include masm32.inc
include user32.inc
;-------
includelib kernel32.lib
includelib masm32.lib
includelib user32.lib
Magic_Number PROTO :DWORD
comment µ
Explication:
on prend le problème a l'envers,dans edx on a un nombre = resultat
de la division de N/D * 2p32 (p = puissance) dans edx
result = (N/D) * 2p32 ;N= differents entiers
N varie et seul D nous interesse
On divise les deux membres de l'expression par N
1/D = 2p32/D ;-- on vient de definir l'inverse d'un nombre pour le processeur --
;-- en multipliant un nombre par l'inverse du diviseur ,on opère une division --
;-- par la multiplication ------
1 0000 0000h = 2p32
Un registre de 32 bits ne peut contenir qu'un nombre de 2p32 - 1 = FFFF FFFFh
Pour le processeur,on pose 2p32/D = FFFFFFFFh/D + 1 = magic number
µ
.const
.data
hInstance dd 0
tampAscii db 10 dup (0)
titre db "Nombre de resultats exacts",0
.code
start:
;---- code here --------
invoke Magic_Number,325847
invoke dwtoa,eax,addr tampAscii
invoke MessageBox,NULL,ADDR tampAscii,addr titre,MB_OK
invoke ExitProcess,0
;on va diviser par la division puis par la multiplication le nombre passer en
;appel par une suite de nombre de 1 a 10000,on compte le nombre de resultats justes
;la divisision par 1 echoue FFFFFFFFFh +1= -1+1=0
Magic_Number PROC dividende:DWORD
Local diviseur:DWORD
local result:DWORD
Local magic:DWORD
Local reste:DWORD
Local retour:DWORD
mov retour,0 ;compteur de resultats corrects
mov diviseur,1
;mov dividende,325847
continue:
;division normale
mov edx,0
mov ecx,diviseur
mov eax,dividende
div ecx
mov result,eax
mov reste,edx
;we keep the result for comparison.
;calcul du nombre magique,FFFFFFFF/D
;--- on utilise la division pour obtenir le résultat -------
mov edx,0
mov eax,-1
mov ecx,diviseur
div ecx
inc eax
mov magic,eax
;connaissant le nombre magique,on procède à la multiplication
mov edx,0
mov ecx,magic
mov eax,dividende
mul ecx
.if edx == result ;le resultat est dans edx (N/D) * 2p32
inc retour ;et non pas eax
.endif
inc diviseur
.if diviseur != 10001
jmp continue
.endif
FindeMagic_Number:
mov eax,retour
ret
Magic_Number endp
;################################################################
end start
Conclusion :
la méthode peut fonctionner pour n'importe quel dimension de nombre,word qword...
Vous n'êtes pas encore membre ?
inscrivez-vous, c'est gratuit et ça prend moins d'une minute !
Les membres obtiennent plus de réponses que les utilisateurs anonymes.
Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.
Le fait d'être membre vous permet d'avoir des options supplémentaires.