Multiplier pour diviser, nombres magiques

Soyez le premier à donner votre avis sur cette source.

Snippet vu 3 291 fois - Téléchargée 15 fois

Contenu du snippet

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...

A voir également

Ajouter un commentaire

Commentaires

Messages postés
559
Date d'inscription
jeudi 28 novembre 2002
Statut
Non membre
Dernière intervention
27 octobre 2020
2
La réponse est içi avec le code source.
http://win32assembly.programminghorizon.com/files/magicnumber.zip.
Même résultat que le code de brunews et la même limitation a des nombres de 29 bits,a cause du décalage de trois.
Max:1fffffffh
Messages postés
559
Date d'inscription
jeudi 28 novembre 2002
Statut
Non membre
Dernière intervention
27 octobre 2020
2
citation:
Si on veut vraiment coder obsolete, il reste a transposer "div r10" de bnRecidivDW(), c'est quand meme pas la mer à boire pour un codeur ASM.

Voici donc le code:
; void bnRecidivDW(ECX DWORD v, RDX LPBNRECIDIV prcdvs)
ALIGN 16
bnRecidivDW PROC
mov r10d, ecx
mov r9, rdx ; R9 = prcdvs
xor ecx, ecx ; pour result coherent de BSR
lea r8d, [r10d - 1]

bsr ecx, r10d
test r8d, r10d
mov [r9 + 8], ecx ; prcdvs->decSHR IMPEC
mov eax, 1
je short POWEROF2
shl eax, cl

shl rax, 32
xor edx, edx
div r10

add eax, 1
xor ecx, ecx ; NON pow2
mov [r9], eax ; prcdvs->loMagic
POWEROF2:
mov [r9 + 12], ecx
ret 0
bnRecidivDW ENDP

;-------------------------------------------------------------
SANS COMMENTAIRES
;-------------------------------------------------------------
Messages postés
21042
Date d'inscription
jeudi 23 janvier 2003
Statut
Modérateur
Dernière intervention
21 août 2019
24
mais enfin, on n'est pas sur telecharger.com, je donne l'algo et travaille qui veut.

Je tape 13 en zone DWORD, prog donne:
mov eax, dividend
mov ecx, -1651910498
mul ecx
shr edx, 3
EDX = RESULT

C'est pas du 32 bits ?
Messages postés
21042
Date d'inscription
jeudi 23 janvier 2003
Statut
Modérateur
Dernière intervention
21 août 2019
24
Clair que le soft est en x64, nous sommes fin 2012.

Tu ne vois pas que la zone DWORD fait le 32 bits ?

Si on veut vraiment coder obsolete, il reste a transposer "div r10" de bnRecidivDW(), c'est quand meme pas la mer à boire pour un codeur ASM.
Messages postés
559
Date d'inscription
jeudi 28 novembre 2002
Statut
Non membre
Dernière intervention
27 octobre 2020
2
Ce qui serait sympa , c'est de répondre à la question du 32 bits ,je ne vois que du 64 bits !,Inutilisable dans ce cas.
Afficher les 13 commentaires

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.