Assembleur 64 avec le compilateur nasm
Vous souhaitez réagir à ce message ? Créez un compte en quelques clics ou connectez-vous pour continuer.
Le deal à ne pas rater :
Jeux, jouets et Lego : le deuxième à -50% (large sélection)
Voir le deal

Affichage de l'ensemble de Mendelbrot

Aller en bas

Affichage de l'ensemble de Mendelbrot Empty Affichage de l'ensemble de Mendelbrot

Message par Admin Ven 22 Sep - 20:26

Ce programme est aussi un programme de gestion d’image. Ici nous allons afficher l’ensemble fractal de Mendelbrot. Les flèches et les symboles + et – permettront de naviguer et de jouer sur la taille de l’image affichée.
Ce programme est succinct et peut être grandement amélioré.
Il reprend la trame d’affichage d’une fenêtre comme nous l’avons déjà vu dans les programmes précédents.
Nous commençons par créer une image vide qui servira de support au dessin des points de l’ensemble. Dans la procedure CreationImageMem nous appelons les fonctions CreateCompatibleDC pour créer un contexte en mémoire puis la fonction CreateDIBSection qui va créer l’image.
Nous conservons l’adresse retournée dans le pointeur hBitmap.
Après la création de la fenêtre comme déjà vu, nous ajoutons dans la procédure de gestion des évenements, les instructions concernant le fonctionnement de chaque touche. Les calculs se font en virgule flottante en utilisant les registres de type xmm0 et xmm1.
Dans la partie paint, nous nous contentons de recopier l’image créée en mémoire dans le contexte écran pour assurer son affichage.
Il ne reste plus qu’à effectuer le calcul pour chaque point de l’image afin de déterminer leur couleur. Dans ce calcul, nous nous contentons de déterminer que 2 couleurs : rouge et noir. Le programme peut donc être amélioré pour afficher une gamme de couleurs plus large. Bon courage !!
Code:

;programme calcul et affichage ensemble de mendelbrot en 64 bits
;
;
;============================================================================
; CONSTANTES
;============================================================================
%include "../windowsinc64.inc"
ILGIMAGE  equ 1000
IHTIMAGE  equ 600
ITMAXI  equ 50
;==============================================
; MACROS
;=============================================
;Macro conversion couleur en 0x00bbggrr
;parametre 1 couleur bleu
;parametre 2 couleur verte
;parametre 3 couleur rouge
%macro RGB 3
  mov eax,%3*256*256
  add eax,%2*256
  add eax,%1   
%endmacro

global Main
;extern MessageBoxA    ; tous les noms des fonctions de l'API sont mis dans le fichier include ci dessus
extern afferreur,affmessageP,affconsoleP,afftoutregistreP,afftoutreg8a15P,affmemoireP
;=============================================================================
section .data
;=============================================================================
szTitreFen:  db 'Ensemble de Mandelbrot', 0
szClasseFen db "Classe1",0

;instance de la classe des fenetres
wcexa:  align 8
wcex:
  istruc WNDCLASSEX
  iend
LGWCEX equ $ -    wcex
;instance message
msga: align 8
msg: istruc MSG
    at MSG.fin,  db  "<<<  "
  iend
; instance contexte dessin
ipainta: align 8
ipaint istruc PAINTSTRUCT
  iend 

;BitmapInfo Structure
BitmapInfo istruc BITMAPINFO     
iend
ILGBITMAPINFO equ $ - BitmapInfo
;valeurs de départ des calculs
x1  dq -2.1
x2  dq 2.1
y1  dq -1.2
y2  dq  1.2
nbpixelsx dq 1000.0    ; taille de l'image
nbpixelsy dq 600.0
zoom dq 200.0
zero dq 0.0
un  dq 1.0
deux dq 2.0      
quatre dq 4.0   
dix  dq 10.0
neuf dq 0.9
unun dq 1.1
pointun dq 0.1
;=============================================================================
section .bss
;=============================================================================
hCons  resq 1
hInst  resq 1
hMainWnd resq 1
hdc    resq 1
hdcMem resq 1
hBitmap resq 1
BitmapBits resq 1
dx1 resq 1
;szZoneResult resb 80;
;szResult1  resb 100

;=============================================================================
section .text
;=============================================================================
Main:
    sub rsp, 28h  ; alignement pile et reserve paramètres
    ;recup du handle du programme
   xor rcx,rcx                       
    call GetModuleHandleA
   mov r9,__LINE__
   cmp    eax,NULL
   je       .erreur
   mov [hInst],rax
   ;il faut creer une image en mémoire vide
   call creationImageMem
    ; préparation de la structure de classe des fenêtres
   mov   dword[wcex+WNDCLASSEX.cbSize], LGWCEX  ;taille de la structure de la classe de la fenetre
   mov dword[wcex+WNDCLASSEX.style],CS_HREDRAW | CS_VREDRAW  ; style des fenetres
   mov   qword[wcex+WNDCLASSEX.lpfnWndProc], WndProc ; nom de la procedure qui va gerer les évenements de la fenetre

   xor rax,rax
   mov   dword[wcex+WNDCLASSEX.cbClsExtra], eax    ;raz de ces zones
   mov   dword[wcex+WNDCLASSEX.cbWndExtra], eax

    mov   qword rax, [hInst]
   mov   qword[wcex+WNDCLASSEX.hInstance], rax  ;handle du parent
   mov   qword[wcex+WNDCLASSEX.hIcon], NULL
   ;chargement image curseur souris
   mov rcx,NULL
   mov rdx,IDC_ARROW
   call LoadCursorA
   mov r9,__LINE__ - 1
   cmp eax,NULL
   je .erreur
   mov   qword[wcex+WNDCLASSEX.hCursor], rax
   mov   qword[wcex+WNDCLASSEX.hbrBackground],COLOR_BACKGROUND
   mov   qword [wcex+WNDCLASSEX.lpszMenuName],  NULL
   mov   qword [wcex+WNDCLASSEX.lpszClassName], szClasseFen
   ;creation de la classe de la fenetre (c'est obligatoire)
   mov rcx,wcex
   call RegisterClassExA
   mov r9,__LINE__ - 1
   cmp eax,NULL
   je .erreur
   ;creation de la fenetre
   add rsp,20h
   ;8 parametres donc pas d'alignement à respecter
   push NULL          ; pas de données complémentaires
   push qword[hInst]        ;handle de l'instance du programme
   push NULL          ;fenetre non identifiée
   push NULL          ; pas de fenetre parent
   push 258h          ; hauteur de la fenetre
   push 320h          ; largeur de la fenetre
   push 0Ah            ; position verticale de la fenetre
   push 0Fh          ;position horizontale de la fenetre
   ;
   sub rsp,20h          ; reservation de la place pour les 4 parametres suivants
    mov rcx,NULL          ; pas de style complémentaire
   mov rdx,szClasseFen  ; classe de la fenetre doit être identique à la classe crée par RegisterClassExA
   mov r8,szTitreFen    ; titre de la fenetre
   mov r9,WS_OVERLAPPEDWINDOW   ; fenetre standard avec menu système
    ;
   call CreateWindowExA
   add rsp,40h
   mov r9,__LINE__ - 2
   cmp  eax,NULL
   je  .erreur
   mov   [hMainWnd],eax  ; conserve  le handle de la fenetre
   mov rcx,[hMainWnd]
   mov rdx,SW_SHOWDEFAULT    ; affichage de la fenetre
   call ShowWindow
   ; ici on ne teste pas le code erreur (voir la doc microsoft)
   mov rcx,[hMainWnd]
   call UpdateWindow    ;genere le message WM_PAINT qui dessinera dans la fenêtre
   mov r9,__LINE__ - 1
   cmp  eax,NULL
   je  .erreur
   ;
.boucle_commande:   
    mov rcx,msg
   mov rdx,NULL
   mov r8,0
   mov r9,0
   call GetMessageA    ;récuperation des messages
   cmp eax,0          ; fin de boucle l'utilisateur a fermé la fenetre
   jz .fin_commande
   mov rcx,msg
    call TranslateMessage  ; convertit les actions clavier en message (voir la doc)
   mov rcx,msg
   call DispatchMessageA  ; envoie le message à la procédure de gestion de la fenetre
   jmp .boucle_commande
.fin_commande:   
   mov rcx,0  ; code retour OK
   jmp .fin
.erreur:
    call afferreur
   mov rcx,1  ; code retour erreur
.fin:   
    ; code retour positionné avant
    call ExitProcess
;===========================================================
;Procédure de gestion des évenements de la fenetre
;===========================================================   
WndProc:
%define .hWnd [rbp+16]     ; pour simplifier l'ecriture dans les instructions suivantes
%define .uMsg [rbp+24]
%define .wParam [rbp+32]
%define .lParam [rbp+40]
    ;recuperation des parametres  handle de la fenetre, type du message, wparam, lparam
    ;copie des paramètres dans l'espace réservé
   mov [rsp+8],rcx  ; handle fenêtre
   mov [rsp+16],rdx  ; type de message
   mov [rsp+24],r8  ; wparam
   mov [rsp+32],r9  ; lparam
   enter 0,0      ; eventuellement reserver de la place pour variables locales
   ;ici il faut sauver les registres rbx,rdi,rsi r12 à r15 s'ils sont utilisés
   ;attention si nombre impair il faut aligner la pile
    sub rsp,20h  ; reservation pour les autres appels
   ;traitement des messages
   cmp  rdx,WM_CREATE
    jz .creation
   cmp rdx,WM_PAINT    ; dessin du contenu de  la fenetre
   jz .paint
   cmp  rdx,WM_DESTROY
    jz .destroy
   cmp rdx,WM_COMMAND  ; traitement des evenements
   jz .commande
   cmp rdx,WM_CHAR  ; traitement des touches clavier
   jz .clavier
   cmp rdx,WM_KEYDOWN  ; traitement des touches clavier
   jz .touches
   jmp .retourdefaut
   
.creation:
    ;ici il faut creer une premiere image
   call dessinimage
   jmp .retourproc   
.clavier:    ; pour gerer éventuellement d'autres touches clavier
    mov   rax,r8    ;wParam parametre supplementaire de la commande
   jmp .retourproc   
.touches:
    mov   rax,r8    ;wParam parametre supplementaire de la commande
   cmp rax,6bh    ; touche +  pour grossissement de la figure
   jne .suitet
   movsd xmm0,[x2]    ;calcul de la distance sur l'axe des x
   subsd xmm0,[x1]
   mulsd xmm0,[neuf]  ; on multiplie par 0,9 
   addsd  xmm0,[x1]  ; et on l'ajoute  à l'origine pour
   movsd [x2],xmm0    ; calculer la fin

   movsd xmm0,[y2]  ; on fait la même chose sur l'axe des y
   subsd xmm0,[y1]
   mulsd xmm0,[neuf]
   addsd  xmm0,[y1]
   movsd [y2],xmm0
   jmp .touchesfin
.suitet:
   cmp rax,6dh    ; touche - pour revenir en arrière
   jne .suitet1
   movsd xmm0,[x2]    ; calcul de la distance sur l'axe des x
   subsd xmm0,[x1]
   mulsd xmm0,[unun]  ; on multiplie par 1,1
   addsd  xmm0,[x1]    ; ajout à l'origine
   movsd [x2],xmm0    ; pour calculer la fin
   movsd xmm0,[y2]    ; et on fait la même chose sur l'axe des y
   subsd xmm0,[y1]
   mulsd xmm0,[unun]
   addsd  xmm0,[y1]
   movsd [y2],xmm0
   jmp .touchesfin
.suitet1:
   cmp rax,25h    ; touche flèche gauche pour deplacer la figure
   jne .suitet2
   movsd xmm0,[x2]  ; calcul de la largeur de la figure
   subsd xmm0,[x1] 
   divsd xmm0,[dix]  ; calcul d'un dizième   
   movsd xmm1,[x1]    ; soustraction de l'origine pour se deplacer à gauche
   subsd xmm1,xmm0
   movsd [x1],xmm1
   movsd xmm1,[x2]  ; puis soustraction de la fin de la figure
   subsd xmm1,xmm0
   movsd [x2],xmm1   
   jmp .touchesfin
.suitet2:
   cmp rax,27h    ; touche flèche droite pour deplacer la figure
   jne .suitet3
   movsd xmm0,[x2]  ; calcul de la largeur de la figure
   subsd xmm0,[x1]
   divsd xmm0,[dix]  ; calcul d'un dizième   
   movsd xmm1,[x1]  ; ajout à l'origine pour deplacer la figure vers la droite
   addsd xmm1,xmm0  ; d'un dixième
   movsd [x1],xmm1    ; puis ajout à l'extrèmité
   movsd xmm1,[x2]
   addsd xmm1,xmm0
   movsd [x2],xmm1   
   jmp .touchesfin   
.suitet3:
   cmp rax,26h        ; touche flèche haut pour deplacer la figure
   jne .suitet4
   movsd xmm0,[y2]
   subsd xmm0,[y1]
   divsd xmm0,[dix]
   movsd xmm1,[y1]
   addsd xmm1,xmm0
   movsd [y1],xmm1
   movsd xmm1,[y2]
   addsd xmm1,xmm0
   movsd [y2],xmm1   
   jmp .touchesfin
.suitet4:
   cmp rax,28h    ; touche flèche bas pour deplacer la figure
   jne .suitet5
   movsd xmm0,[y2]
   subsd xmm0,[y1]
   divsd xmm0,[dix]
   movsd xmm1,[y1]
   subsd xmm1,xmm0
   movsd [y1],xmm1
   movsd xmm1,[y2]
   subsd xmm1,xmm0
   movsd [y2],xmm1   
   jmp .touchesfin
.suitet5:   
   jmp .retourproc   
.touchesfin:             ; dessin de la fenêtre pour afficher la nouvelle image
   call dessinimage      ; calcul de la nouvelle image
   mov rcx,.hWnd
   mov rdx,NULL
   mov r8,FALSE
   call InvalidateRect
   jmp .retourproc   
.paint:
    ; rcx doit contenir le handle de la fenetre depuis le début de la procédure
   mov  rdx,  ipaint  ; structure
   call BeginPaint  ; debut du dessin
   mov   [hdc], rax
   ;ici il faut copier l'image à afficher.
   ; recopie de l'image du contexte mémoire dans le contexte écran
   add rsp,20h
   sub rsp,8h
   push SRCCOPY
   push 0            ; position gauche origine
   push 0            ; position haute origine
   push  qword[hdcMem]    ; origine
   push IHTIMAGE  ; hauteur destination
   sub rsp,20h
   mov rcx,[hdc]  ; destination
   mov rdx, 0        ; position haut destination
   mov r8,0        ; position gauche  destination
   mov r9,ILGIMAGE  ; largeur destination
   call BitBlt          ;transfert de l'image à l'emplacement desiré
   add rsp,30h  ;5 parametres et un alignement
   mov r9,__LINE__ - 1
   cmp rax,NULL
   je .erreur

   mov rcx,[rbp+16]  ;handle de la fenetre
   mov rdx, ipaint  ; structure
   call EndPaint      ; fin du dessin
   jmp .retourproc   
.commande:
   mov   rax,r8    ;wParam parametre supplementaire de la commande
   and   rax,0FFFFh

;   cmp rax,IDM_EXIT    ; menu quitter
;   je .close
   jmp .retourproc   

.close:
   ; ici rcx doit encore contenir le handle de la fenetre
   call DestroyWindow    ; destruction de la fenetre
   jmp .retourproc         
.destroy:
    xor rcx,rcx
    call PostQuitMessage
   jmp .retourproc   
.erreur:
    call afferreur   
.retourdefaut:         ; appel par defaut pour tous les autres messages   
   call DefWindowProcA
.retourproc:   
    add rsp,20h
   ;ici il faut restaurer les registres sauvegardés
   ;attention si nombre impair il faut aligner la pile
   leave  ; restaure
   ret

;============================================================
;creation image en memoire
;============================================================
creationImageMem:
    sub rsp,28h
   xor rax,rax 
   mov rcx,NULL
   call CreateCompatibleDC  ;création d'un contexte en memoire
   mov r9,__LINE__
   cmp eax,NULL
   je .erreur
    mov [hdcMem], rax;
    mov rcx,BitmapInfo
    call initStrucInfo   
   xor rax,rax 
   add rsp,20h
   push NULL
   push NULL
   sub rsp,20h
   mov rcx,[hdcMem]
   mov rdx,BitmapInfo
   mov r8,DIB_RGB_COLORS
    mov r9,BitmapBits             
   call CreateDIBSection  ; creation d'une image en memoire qui va servir de support
   add rsp,10h
   mov r9,__LINE__
   cmp eax,NULL
   je .erreur
   mov [hBitmap],rax
   jmp .fin
.erreur:
    call afferreur   
   mov rax,FALSE
.fin:   
   add rsp,28h
   ret          
;===============================================================================
;init de la structure BITMAPINF
;================================================================================   
;rcx contient l'adresse de la structure
initStrucInfo:
    mov dword[rcx+BITMAPINFO.biSize], ILGBITMAPINFO    ;longueur de la structure
   mov dword[rcx+BITMAPINFO.biWidth],ILGIMAGE    ;largeur image en dword
   mov dword[rcx+BITMAPINFO.biHeight],IHTIMAGE  ; hauteur image en dword
   mov word[rcx+BITMAPINFO.biPlanes ],1
   mov word[rcx+BITMAPINFO.biBitCount ],32  ; codage sur 32 bits
   ret    
;===================================================
; dessin image
;===================================================

dessinimage:
   sub rsp,28h
   xor rax,rax
   mov rcx,[hdcMem]  ; selection de l'emplacement de l'image
   mov rdx,[hBitmap]  ; dans le contexte mémoire
    call SelectObject
     mov r9,__LINE__
   cmp eax,NULL
   je .erreur
   call calcul1
   jmp .fin
.erreur:
    call afferreur   
   mov rax,FALSE
.fin:   
   add rsp,28h
   ret   
;===================================================
; calcul pour chaque pixel de l'image
;==================================================
calcul1:
    sub rsp,28h
   movsd xmm10,[x2]
   subsd xmm10,[x1]
   divsd xmm10,[nbpixelsx]  ; calcul pas x
   movsd [dx1],xmm10
   movsd xmm12, [y2]
   subsd xmm12,[y1]
   divsd xmm12,[nbpixelsy]  ; calcul pas y
   mov rbx,0        ; position X du pixel
.boucle:   
   cvtsi2sd xmm13, rbx      ; convertit entier en double
   mulsd xmm13,xmm10
   addsd xmm13,[x1]
    mov r13,0      ; position Y du pixel
.boucle1:
    cvtsi2sd xmm14, r13    ; convertit entier en double
   mulsd xmm14,xmm12
   addsd xmm14,[y1]
   ;suite calcul
   movsd xmm5, [zero]
   movsd xmm6, [zero]
   mov r9,0
.boucleFaire:          ; coeur du calcul
    movsd xmm7,xmm5
    mulsd xmm5,xmm5
   movsd xmm0,xmm6
    mulsd xmm0,xmm0   
   subsd xmm5,xmm0
   addsd xmm5,xmm13
   mulsd xmm6,[deux]
   mulsd xmm6,xmm7
   addsd xmm6,xmm14
   inc r9
   cmp r9,ITMAXI
   jge  .suite
   movsd xmm0,xmm5
   mulsd xmm0,xmm5
   movsd xmm7,xmm6
   mulsd xmm7,xmm6
   addsd xmm0,xmm7
   ucomisd  xmm0,[quatre]
   jb .boucleFaire   
   xor rdx,rdx
   mov rax,r9
   mov r9,255
   mul r9
   mov r9,ITMAXI
   div r9
   call dessinpixel
   jmp .suite2
.suite:   
   ;suite des boucles
   RGB 0,0,0  ;noir
   call dessinpixel  ; mise à jour du pixel
   
.suite2:   
   inc r13
   cmp r13,IHTIMAGE-1
   jle .boucle1
   inc rbx
   cmp rbx,ILGIMAGE-1
   jle  .boucle
   jmp .fin
.erreur:
    call afferreur   
   mov rax,FALSE
.fin:   
   add rsp,28h
   ret
   
;===========================================================
;dessin pixel
;===========================================================
;rax contient la couleur
;rbx la position en X
;r13 la position en Y
dessinpixel:
    sub rsp,28h
   mov rcx,[hdcMem]  ; dans le contexte memoire
   mov rdx,rbx
   mov r8,r13
   mov r9,rax    ; code couleur
   call SetPixel
   mov r9,__LINE__
   cmp eax,-1
   je  .erreur
   jmp .fin
.erreur:
    call afferreur   
   mov rax,FALSE
.fin:   
   add rsp,28h
   ret   
   
Admin
Admin
Admin

Messages : 38
Date d'inscription : 28/11/2016

https://assembleur64.kanak.fr

Revenir en haut Aller en bas

Revenir en haut

- Sujets similaires

 
Permission de ce forum:
Vous ne pouvez pas répondre aux sujets dans ce forum