Comme l'apprentissage passe par la démonstration, voici un petit exemple très simple : le LOTO.
L'idée du programme est double :
1) prendre une console, générer un tirage et vérifier un algorithme de génération aléatoire
2) expliquer la structure d'un fichier .ASM
Le programme fonctionne avec MASM32 sur un 586. Vous trouverez les versions :
- Pascal de haut niveau (version de "base")
- ASM décommentée
- ASM avec ses nombreux commentaires
L'algorithme RANDOM est tiré de Pascal/Delphi. Mais comme je l'ai retouché pour le faire sortir dans DL, la version Pascal qui sort dans AL se retrouve légèrement plus lente que le programme ASM. Mais le code est déjà très compact et il est très difficile d'accélérer plus.
Bref, tout commentaire est bienvenu... J'espère juste de ne pas avoir dit de bêtises.
Source / Exemple :
; Console Assemble & Link
.586
.model flat, stdcall
option casemap :none
include \masm32\include\windows.inc
include \masm32\macros\macros.asm
include \masm32\include\masm32.inc
include \masm32\include\gdi32.inc
include \masm32\include\user32.inc
include \masm32\include\kernel32.inc
includelib \masm32\lib\masm32.lib
includelib \masm32\lib\gdi32.lib
includelib \masm32\lib\user32.lib
includelib \masm32\lib\kernel32.lib
.data
DMaxInt EQU 49d
SCrLf EQU 13,10
SDoubleLine DB SCrLf,SCrLf,0
SHeader DB "-------------------------------------------------------------------------",SCrLf, \
" :: Application Loto MAsm32 ::",SCrLf, \
"-------------------------------------------------------------------------",SCrLf,SCrLf,0
SMenuItem DB " 1: G?n?rer un tirage du loto",SCrLf,SCrLf, \
" 2: V?rifier l'homor?partition",SCrLf,SCrLf, \
" 3: Quitter",SCrLf, \
SCrLf,SCrLf,0
SSpace DB " ",0
SRandomize EQU "M?thode de randomisation :",SCrLf,SCrLf, \
" 1) TickCount Windows - D?faut",SCrLf, \
" 2) Processeur - Pentium (x586)",SCrLf, \
" 3) Horloge syst?me",SCrLf,SCrLf, \
"> ",0
SSelectItem EQU "Votre choix : ",0
SIteration EQU "Nombre de balles ? tirer : ",0
SMaskResult DB " %d -> %d",SCrLf,0
SMaskStats DB SCrLf,SCrLf, \
" Valeur minimale : %d",SCrLf, \
" Valeur maximale : %d",SCrLf, \
" Delta : %d",SCrLf, \
" Temps requis : %d ms",SCrLf,SCrLf,0
.data?
RandBase DD ?
BRet DB ?
AAllDrawn DB 7 dup(?)
ACountDraws DD 49 dup(?)
DTiming DD ?
SOutput DB 255 dup(?)
DMinVal DD ?
DMaxVal DD ?
.code
Randomize proc
LOCAL RSysTime:SYSTEMTIME
.IF AL == 2d
RDTSC
.ELSEIF AL == 3d
invoke GetSystemTime, ADDR RSysTime
MOVZX EAX, Word PTR RSysTime.wHour
IMUL EAX,60
ADD AX, Word PTR RSysTime.wMinute
IMUL EAX, 60
MOVZX EDX, Word PTR RSysTime.wSecond
ADD EAX, EDX
IMUL EAX, 1000
MOV DX, Word PTR RSysTime.wMilliseconds
ADD EAX, EDX
.ELSE
CALL GetTickCount
.ENDIF
MOV RandBase, EAX
RET
Randomize endp
DisplayHeader proc
cls
invoke StdOut, ADDR SHeader
RET
DisplayHeader endp
Menu proc
@@:
CALL DisplayHeader
invoke StdOut, ADDR SMenuItem
MOV EAX, sval(input(SSelectItem))
.IF EAX == 1d
CALL DrawLoto
JMP @B
.ELSEIF EAX == 2d
CALL CheckLoto
JMP @B
.ELSEIF EAX != 3d
JMP @B
.ENDIF
RET
Menu endp
IsAlreadyDrawn proc uses ECX EBX
AND BRet, 0b
@SiDebut:
MOV AL, Byte PTR [EBX]
CMP AL, DL
JNE @F
OR BRet, 1b
JMP @SiFin
@@:
CMP CL, 00h
JE @SiFin
DEC CL
DEC EBX
JMP @SiDebut
@SiFin:
RET
IsAlreadyDrawn endp
DrawLoto proc uses EBX
LOCAL DBoucle:DWord
invoke StdOut,ADDR SDoubleLine
LEA EBX, AAllDrawn
XOR ECX, ECX
@@:
CALL Random
CALL IsAlreadyDrawn
CMP BRet, 1b
JE @B
MOV Byte PTR [EBX], DL
INC EBX
INC ECX
CMP ECX, 7d
JNE @B
MOV DBoucle, 1d
LEA EBX, AAllDrawn
@@:
MOVZX EAX, Byte PTR [EBX]
INC EAX
invoke wsprintf, ADDR SOutput, ADDR SMaskResult, DBoucle, EAX
invoke StdOut, ADDR SOutput
INC EBX
INC DBoucle
CMP DBoucle, 7d
JBE @B
MOV EAX, input(0)
RET
DrawLoto endp
Random proc
MOV EAX, DMaxInt
IMUL EDX, RandBase, 08088405h
INC EDX
MOV RandBase, EDX
MUL EDX
RET
Random endp
CheckLoto proc uses EBX
LOCAL Index:DWord
LOCAL DNumber:DWord
invoke StdOut,ADDR SDoubleLine
LEA EBX, ACountDraws
MOV ECX, DMaxInt
@@:
AND DWord PTR [EBX+4*ECX-4], 00h
DEC ECX
JNZ @B
MOV ECX, sval(input(SIteration))
CALL GetTickCount
MOV DTiming, EAX
@@:
CALL Random
INC DWord PTR [EBX+4*EDX]
DEC ECX
JNE @B
CALL GetTickCount
SUB EAX, DTiming
MOV DTiming, EAX
OR DMinVal, 0FFFFFFFFh
AND DMaxVal, 00h
invoke StdOut,ADDR SDoubleLine
AND Index, 00h
@Draw:
MOV ECX, Index
MOV EAX, DWord PTR [EBX+4*ECX]
MOV DNumber, EAX
CMP EAX, DMinVal
JNB @F
MOV DMinVal, EAX
@@:
CMP EAX, DMaxVal
JNA @F
MOV DMaxVal, EAX
@@:
INC Index
CMP Index, 10d
JNB @F
invoke StdOut, ADDR SSpace
@@:
invoke wsprintf, ADDR SOutput, ADDR SMaskResult, Index, DNumber
invoke StdOut, ADDR SOutput
CMP Index, DMaxInt
JNE @Draw
MOV EAX, DMaxVal
SUB EAX, DMinVal
invoke wsprintf, ADDR SOutput, ADDR SMaskStats, DMinVal, DMaxVal, EAX, DTiming
invoke StdOut, ADDR SOutput
MOV EAX, input(0)
RET
CheckLoto endp
start:
@@:
CALL DisplayHeader
MOV EAX, sval(input(SRandomize))
DEC EAX
CMP EAX, 3d
JAE @B
INC EAX
CALL Randomize
CALL Menu
exit
end start
Conclusion :
Vous pouvez toujours aller visiter
http://altert.family.free.fr/
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.