Calculs en hexadécimal sur 64 bits

Description

Utilitaire qui effectue les opérations élémentaires courantes entre deus nombres hexadécimaux (+,-,and,or,xor) sur 64 bits et donne le résultat en hexadécimal et en décimal.Il peut traiter les nombres négatifs et positif.

Source / Exemple :


; #########################################################################

      .386
      .model flat, stdcall
      option casemap :none   ; casse sensible

; #########################################################################

      include \masm32\include\windows.inc
      include \masm32\include\user32.inc
      include \masm32\include\kernel32.inc
      include \masm32\include\gdi32.inc
      include \masm32\include\masm32.inc

      includelib \masm32\lib\user32.lib
      includelib \masm32\lib\kernel32.lib
      includelib \masm32\lib\gdi32.lib
      includelib \masm32\lib\masm32.lib

; #########################################################################

        ;=============
        ; Local macros
        ;=============
  
        szText MACRO Name, Text:VARARG
          LOCAL lbl
            jmp lbl
              Name db Text,0
            lbl:
          ENDM
          
        ;=================
        ; Local prototypes
        ;=================
        WndProc  PROTO :DWORD,:DWORD,:DWORD,:DWORD
        Ed1Proc  PROTO :DWORD,:DWORD,:DWORD,:DWORD
        Controle PROTO :DWORD
        Convert  PROTO :DWORD
        dqtoa   PROTO :QWORD, :DWORD, :DWORD
 
        
    .data
        dlgname     db "TESTWIN",0
        M0 db  "Dépasement de capacité : 65 bits!",13,10,10
           db " Pour avoir le résultat exact : ",13,10
           db " HEXA : placer devant, le 65° bit : chiffre 1",13,10
           db " DECI : ajouter 18 446 744 073 709 551 616 ",13,10
           db "                au résutat affiché.",13,10,10
           db "     calculatrice Windows de rigueur",0 
        M1 db "           ATTENTION !!!!",0
        Txt1        db 9  dup (0); Recueuille l'entrée basse 1
        Txt2        db 9  dup (0);     "          "      "   2
        Txt3        db 9  dup (0); Recueuille l'entrée haute 1
        Txt4        db 9  dup (0);     "          "      "   2        
        buff        db 19 dup (0);     "      le résultat en Hexa
;==============================================================
; le tampon suivant est utilisé par dqtoa et doit avoir une
; longueur de 30 octets minimun
;=============================================================         
        StringDec   db 31 dup (0);     "      le résultat en décimal 

    Reste dq 0
    nbch  dd 0
    Cpt   dd 0
    Cpt1  dd 0 
    signe dd 0 

    .data?
        hEdit1      dd ?
        hEdit2      dd ? 
        hEdit3      dd ?
        hEdit4      dd ?
        hEdit5      dd ?
        hEdit6      dd ?                                        
        hButn1      dd ?
        hButn2      dd ?
        hButn3      dd ? 
        hButn4      dd ? 
        hButn5      dd ? 
        hButn6      dd ?  
        hInstance   dd ? 
        hIcon       dd ?
        hText       dd ?
        Nega        dd ?
        Drapo       dd ? 
        lpfnEd1Proc dd ?
        Nb1         dd ? ; chaîne 1 > 64 bits Low
        Nb2         dd ? ; chaine 2 > 64 bits Low
        Nb3         dd ? ; chaîne 1 > 64 bits High
        Nb4         dd ? ; chaîne 2 > 64 bits High 
        Nb5         dd ? ; Résultat Low
        Nb6         dd ? ; Résultat High
        Nb10        dq ?

; #########################################################################

    .code

start:

      invoke GetModuleHandle, NULL
      mov hInstance, eax
      
      ; -----------------------------------------------------
      ; Appel de dialog box stockée dans le fichier ressource 
      ; -----------------------------------------------------
      invoke DialogBoxParam,hInstance,ADDR dlgname,0,ADDR WndProc,0

      invoke ExitProcess,eax

; #########################################################################

WndProc proc hWin   :DWORD,
             uMsg   :DWORD,
             wParam :DWORD,
             lParam :DWORD

      LOCAL Ps :PAINTSTRUCT

      .if uMsg == WM_INITDIALOG
      
        szText dlgTitle,"        Calculs avec des nombres hexadécimaux "
        invoke SendMessage,hWin,WM_SETTEXT,0,ADDR dlgTitle

        invoke LoadIcon,hInstance,200
        mov hIcon, eax

        invoke SendMessage,hWin,WM_SETICON,1,hIcon 

    ;==================================================
    ;Recherche des handles correspondants aux controles
    ;de la boite de dialogue (Edits et boutons)
    ;==================================================

        invoke GetDlgItem,hWin,100
        mov hEdit1, eax

        invoke GetDlgItem,hWin,101
        mov hEdit2, eax

        invoke GetDlgItem,hWin,102
        mov hEdit3, eax

        invoke GetDlgItem,hWin,103
        mov hEdit4, eax

        invoke GetDlgItem,hWin,104
        mov hEdit5, eax

        invoke GetDlgItem,hWin,105
        mov hEdit6, eax        
        
        invoke GetDlgItem,hWin,50
        mov hText, eax

        invoke GetDlgItem,hWin,1000
        mov hButn1, eax

        invoke GetDlgItem,hWin,1001
        mov hButn2, eax

        invoke GetDlgItem,hWin,1002
        mov hButn3, eax

        invoke GetDlgItem,hWin,1003
        mov hButn4, eax

        invoke GetDlgItem,hWin,1004
        mov hButn5, eax

        invoke GetDlgItem,hWin,1005
        mov hButn6, eax 
 
        invoke SetFocus,hEdit1  ; Curseur dans Edit1

        ;==============================================
        ; la proc Ed1Proc va gérer les entrées de Edit1
        ; et de Edit2, controler l'entrée des Nb hexa et
        ; du retour arrière (Del) uniquement.
        ; L'adresse de l'ancienne procédure (WndProc)
        ; est sauvegardée dans lpfnEd1Proc.
        ;==============================================
 
        invoke SetWindowLong,hEdit1,GWL_WNDPROC,Ed1Proc
        mov lpfnEd1Proc, eax
        invoke SetWindowLong,hEdit2,GWL_WNDPROC,Ed1Proc
        mov lpfnEd1Proc, eax
        invoke SetWindowLong,hEdit3,GWL_WNDPROC,Ed1Proc
        mov lpfnEd1Proc, eax
        invoke SetWindowLong,hEdit4,GWL_WNDPROC,Ed1Proc
        mov lpfnEd1Proc, eax        

        xor eax, eax
        ret

      .elseif uMsg == WM_COMMAND
        .if wParam == 1000      ; Ajouter
           mov Nega,0
           invoke Controle,hWin
           .if Drapo == 1
               mov Drapo,0
               ret
           .endif        
           mov eax,Nb1    ; ajouter les 32 bits
           mov ebx,Nb2    ; de poids faible
           add eax,ebx
           mov Nb2,eax
           mov ecx,Nb3    ; ajout des 32 bits 
           mov edx,Nb4    ; de poids forts etde
           adc ecx,edx    ; la retenue si elle existe.
           mov Nb1,ecx
           jnc @F         ; si carry : il y a dépassement
           mov Drapo,1    ; le signaler par le flag
@@:
        ;======================================
        ; résultat > chaîne hexa puis affichage
        ;======================================   
           push ecx
           invoke dw2hex,eax,addr buff+10
           pop ecx
           invoke dw2hex,ecx,addr buff+1          
           invoke SetDlgItemText,hWin,105,addr buff+10
           invoke SetDlgItemText,hWin,104,addr buff+1
           invoke Convert,hWin           
           .if Drapo == 1 
         ;============================================ 
         ; prévenir que le résutat affiché est faux :
         ; en réalité incomplet.
         ;============================================
               mov Drapo,0
               invoke MessageBox,hWin,addr M0,addr M1,MB_OK
           .endif    

        .elseif wParam == 1001   ; Soustraire
           invoke Controle,hWin
           mov Nega,0
           mov eax,Nb1
           mov ebx,Nb2
           sub eax,ebx 
           mov Nb2,eax                    
           mov edx,Nb4
           mov ecx,Nb3
           adc edx,0
           sub ecx,edx
           mov Nb1,ecx
           jnc @F      ; si carry : résultat négatif
           mov Nega,1
@@: 
           xor esi,esi          
           .if Nega==1
         ;=========================================
         ; négatif, faire précéder le résultat
         ; décimal du signe moins.
         ;=========================================   
               lea esi,buff                                                                                                        
               mov byte ptr[esi],2Dh
           .else
               lea esi,buff 
               mov byte ptr[esi],2Bh
           .endif   
           push ecx
         ;=============================================
         ; placer les 2 chaines hexa au bon endroit
         ; dans le buffer et les afficher dans les 
         ; edits correspondants.
         ;=============================================
           invoke dw2hex,eax,addr buff+10
           pop ecx
           invoke dw2hex,ecx,addr buff+1           
           invoke SetDlgItemText,hWin,105,addr buff+10
           invoke SetDlgItemText,hWin,104,addr buff
         ;==============================================
         ; appeler la procédure chargée de convertir
         ; un QWORD en chaine décimale et de l'afficher.
         ;==============================================  
           invoke Convert,hWin
           
        .elseif wParam == 1002    ; effacer
            invoke SendMessage,hEdit1,WM_SETTEXT,0,NULL 
            invoke SendMessage,hEdit2,WM_SETTEXT,0,NULL
            invoke SendMessage,hEdit3,WM_SETTEXT,0,NULL
            invoke SendMessage,hEdit4,WM_SETTEXT,0,NULL 
            invoke SendMessage,hEdit5,WM_SETTEXT,0,NULL
            invoke SendMessage,hEdit6,WM_SETTEXT,0,NULL                       

        .elseif wParam == 1003    ; and
           invoke Controle,hWin
           mov eax,Nb1
           mov ebx,Nb2
           and eax,ebx
           mov Nb2,eax
           invoke dw2hex,eax,addr buff+10
           invoke SetDlgItemText,hWin,105,addr buff+10
           mov eax,Nb3
           mov ebx,Nb4
           and eax,ebx
           mov Nb1,eax
           invoke dw2hex,eax,addr buff+1
           invoke SetDlgItemText,hWin,104,addr buff+1
           invoke Convert,hWin           
           
        .elseif wParam == 1004    ; or
           invoke Controle,hWin
           mov eax,Nb1
           mov ebx,Nb2
           or eax,ebx
           mov Nb2,eax
           invoke dw2hex,eax,addr buff+10
           invoke SetDlgItemText,hWin,105,addr buff+10
           mov eax,Nb3
           mov ebx,Nb4
           or eax,ebx
           mov Nb1,eax
           invoke dw2hex,eax,addr buff+1
           invoke SetDlgItemText,hWin,104,addr buff+1
           invoke Convert,hWin  

        .elseif wParam == 1005    ; xor
           invoke Controle,hWin
           mov eax,Nb1
           mov ebx,Nb2
           xor eax,ebx
           mov Nb2,eax
           invoke dw2hex,eax,addr buff+10
           invoke SetDlgItemText,hWin,105,addr buff+10
           mov eax,Nb3
           mov ebx,Nb4
           xor eax,ebx
           mov Nb1,eax
           invoke dw2hex,eax,addr buff+1
           invoke SetDlgItemText,hWin,104,addr buff+1
           invoke Convert,hWin  
        .endif

      .elseif uMsg == WM_CLOSE
        invoke EndDialog,hWin,0

      .elseif uMsg == WM_PAINT
        invoke BeginPaint,hWin,ADDR Ps
      ; --------------------------------------------
      ; Les fonctions suivantes sont dans MASM32.LIB
      ; Elles tracent les cadres autour des controles 
      ; --------------------------------------------
        invoke FrameGrp,hButn1,hButn3,6,1,0
        invoke FrameGrp,hButn4,hButn6,6,1,0
        invoke FrameWindow,hWin,0,1,1
        invoke FrameWindow,hWin,1,1,0

        invoke EndPaint,hWin,ADDR Ps
        xor eax, eax
        ret

      .endif

    xor eax, eax  
    ret

WndProc endp

; ########################################################################
 

Ed1Proc proc hCtl: DWORD,
             uMsg1: DWORD,
             wParam1: DWORD,
             lParam1: DWORD

    .if uMsg1 == WM_CHAR
        .if wParam1 == 8   ; touche Suppr
            jmp accept
        .endif
        .if wParam1 < "0"
           .if wParam1 == 02Dh ; touche moins
             jmp accept
           .else 
             xor eax,eax
             ret
           .endif
        .endif
        .if wParam1 > "9" 
           .if wParam1 >= 'A' && wParam1 <= 'F'
               jmp accept
           .endif
           .if  wParam1 >= 'a' && wParam1 <= 'f'
               jmp accept
           .endif    
           xor eax,eax
           ret
        .endif
    .endif

 accept:   ; Rend le contrôle à la procédure normale.
      invoke CallWindowProc, lpfnEd1Proc, hCtl, uMsg1,wParam1,lParam1
    ret

Ed1Proc endp

; #########################################################################

Controle proc hCtrl:DWORD

  ;====================================
  ; Remise à zéro des buffers de sortie
  ;====================================
    lea edi,buff
    mov ecx,19
    mov al,0
    rep stosb
    mov Nb1,0
    mov Nb2,0
    
  ;=====================================
  ; Récupération des textes hexa entrés.
  ; 9 caractères maximum (8 hexa + 0)
  ;=====================================
    invoke GetDlgItemText,hCtrl,101,addr Txt1,9
    invoke GetDlgItemText,hCtrl,103,addr Txt2,9
    invoke GetDlgItemText,hCtrl,100,addr Txt3,9
    invoke GetDlgItemText,hCtrl,102,addr Txt4,9    
  ;================================
  ; Controle si une entrée est vide
  ;================================
    lea esi,Txt3       
    lea edi,Txt1
  szText t1,"1er nombre nul? ..bizarre !!"    
    .if (byte ptr[esi] == 0) && (byte ptr[edi] == 0)
        invoke MessageBox,0,addr t1,0,0
        mov Drapo,1
        ret
    .endif
    lea esi,Txt4
    lea edi,Txt2 
 szText t2,"Il faut 2 nombres pour opérer !!"           
    .if (byte ptr [esi]==0) && (byte ptr[edi] == 0)
        invoke MessageBox,0,addr t2,0,0
        mov Drapo,1
        ret
    .endif
  ;=================================
  ; 4 Chaînes hexa > 4 nombres DWORD
  ;=================================    
    lea esi,Txt3
    lea edi,Txt4
    .if byte ptr[esi]==0
        mov Nb3,0
    .else 
        invoke htodw,addr Txt3
        mov Nb3,eax
    .endif
    .if byte ptr[edi]==0
        mov Nb4,0
    .else
        invoke htodw,addr Txt4
        mov Nb4,eax
    .endif                

    lea esi,Txt1
    lea edi,Txt2
    .if byte ptr[esi] == 0
        mov Nb1,0
    .else   
        invoke htodw,addr Txt1
        mov Nb1,eax
    .endif
    .if byte ptr[edi] == 0
        mov Nb2,0
    .else        
        invoke htodw,addr Txt2
        mov Nb2,eax
    .endif    

    ret
Controle endp

; #########################################################################

Convert Proc Hwin :DWORD
;=======================================================
; récupération de 2 DWORD et transformation en 1 QWORD
;======================================================    
    mov eax,Nb1
    mov edx,Nb2
    mov esi,offset Nb10
    mov [esi],edx
    add esi,4
    mov [esi],eax

    cmp Nega,1
    jne Positif
    
    invoke dqtoa,Nb10,addr StringDec,1
    mov Nega,0
    jmp @F
Positif:
    invoke dqtoa,Nb10,addr StringDec,0
@@:        
    invoke SetDlgItemText,Hwin,106,addr StringDec
    ret
Convert endp        

;=============================================================
; la proc suivante (que j'utilise dans plusieurs utilitaires)
; est normalement intégrée dans ma bibliothèque masm32.lib
;=============================================================
dqtoa proc Nombre:QWORD,buffer:DWORD,sens:DWORD

         pushad
         mov eax,sens
         mov signe,eax
         lea esi,Nombre
         lea edi,Reste
         xor eax,eax
         mov [edi],eax
         mov [edi+4],eax
         mov ecx,64
         mov Cpt1,63
         mov eax,[esi]
         mov ebx,[esi+4]
         cmp signe,1
         jne @F
         not eax
         not ebx
         add eax,1
         adc ebx,0
@@:
         push ecx
         mov ecx,[edi]
         mov edx,[edi+4] 
         shl ebx,1
         adc ecx,0
         shl eax,1
         adc ebx,0
         mov [esi],eax
         mov [esi+4],ebx
         mov [edi],ecx
         push eax
         push ebx
         mov eax,540BE400h
         mov ebx,00000002h
         cmp edx,ebx
         ja @0
         jb @1
         cmp ecx,eax
         jb @1
@0:
         sub ecx,eax
         sbb edx,ebx
         mov [edi],ecx
         mov [edi+4],edx
         mov Cpt,1
         jmp stop
@1:
         mov Cpt,0
stop:
         pop ebx
         pop eax
         dec Cpt1
         js yapu
         shl edx,1
         clc
         shl ecx,1
         adc edx,0
         mov [edi],ecx
         mov [edi+4],edx
yapu:
         add eax,Cpt
         mov [esi],eax
         pop ecx
         loop @B
         mov eax,[edi]
         mov edx,[edi+4]
         mov ecx,10
         mov edi,buffer
         add edi,29
@@:
         div ecx
         add dl,30h
         mov byte ptr[edi],dl
         dec edi
         xor dl,dl
         inc nbch
         cmp eax,0
         je @F
         jmp @B
@@:
         mov eax,[esi]
         mov edx,[esi+4]
         cmp eax,0 ; eax nul : voir edx
         jne @2    ; non nul : traiter
         cmp edx,0 ; edx également nul
         je @F     ; passer au formatage.
@2:
 ; si la division par 10 000 000 000 tombe sur
 ; un ou des zéro, ils n'apparaissent pas,
 ; il faut donc les restituer mais
 ; uniquement si il ya qq. chose à placer devant
         cmp nbch,10
         je @3      
         mov byte ptr[edi],30h
         dec edi     
         inc nbch
         jmp @2
@3:
         div ecx
         add dl,30h
         mov byte ptr[edi],dl
         dec edi
         xor dl,dl
         inc nbch
         cmp eax,0
         je @F
         jmp @3
@@:
         inc edi
         mov esi,edi
@@:
         cmp byte ptr[esi],30h
         jne @F
         inc esi
         jmp @B
@@:
         mov edi,buffer
         cmp signe,1
         jne @F
         mov byte ptr[edi],2Dh
         inc edi
         mov byte ptr[edi],20h
         inc edi
@@:
         mov eax,nbch
         mov ecx,3
         div ecx
         cmp edx,0
         je ici
         mov ecx,edx

@@:      
         cmp byte ptr [esi],0
         je stp
         movsb
         loop @B 
         mov byte ptr [edi],20h
         inc edi
ici:     
         mov ecx,3
@@:      
         cmp byte ptr [esi],0
         je stp
         movsb
         loop @B          
         mov byte ptr [edi],20h
         inc edi
         jmp ici
stp:     
         mov byte ptr [edi],0  
         mov nbch,0
         popad
         ret

dqtoa endp 
        
;####################################################
   
end start  ; Fin du programme
;########################################

#include "\masm32\include\resource.h"

TESTWIN DIALOGEX MOVEABLE IMPURE LOADONCALL DISCARDABLE	200, 40, 241, 134, 0
STYLE 0x0004  | WS_CAPTION | WS_SYSMENU | WS_VISIBLE | WS_POPUP
CAPTION "Dialog"
FONT 8, "Ms Serif", 700, 0 /*FALSE*/
BEGIN
    EDITTEXT        100,   56,13,49,13, ES_AUTOHSCROLL | ES_LEFT, , 0
    EDITTEXT        101,  106,13,49,13, ES_AUTOHSCROLL | ES_LEFT, , 0
    EDITTEXT        102,   56,32,49,13, ES_AUTOHSCROLL | ES_LEFT, , 0    
    EDITTEXT        103,  106,32,49,13, ES_AUTOHSCROLL | ES_LEFT, , 0
    EDITTEXT        104,   56,50,49,14, ES_AUTOHSCROLL | ES_LEFT, , 0
    EDITTEXT        105,  106,50,49,13, ES_AUTOHSCROLL | ES_LEFT, , 0 
    EDITTEXT        106,   56,69,98,13, ES_AUTOHSCROLL | ES_LEFT, , 0       
 
    PUSHBUTTON      "Ajouter",    1000, 	180,12,40,16, 0, , 0
    PUSHBUTTON      "Soustraire", 1001, 	180,32,40,16, 0, , 0
    PUSHBUTTON      "Effacer",    1002,   180,52,40,16, 0, , 0
    PUSHBUTTON      "AND",        1003,    56,98,31,16, ,0
    PUSHBUTTON      "OR",         1004,    90,98,30,16, ,0
    PUSHBUTTON      "XOR",        1005,   125,98,30,16, ,0 
    
    CTEXT           "High 64 bits",50,60, 2,30,9,SS_LEFT, , 0
    CTEXT           "Low 64 bits", 60,109 2,30,9,SS_LEFT, , 0
    CTEXT           "Entrée 1", 20,   11,14,35,10,SS_LEFT, , 0
    CTEXT           "Entrée 2", 30,   11,34,35,8, SS_LEFT, , 0
    CTEXT           "Résultat", 40,   11,49,35,8, SS_LEFT, , 0
    CTEXT           "   Hexa",  40,   11,57,35,8, SS_LEFT, , 0 
    CTEXT           "Résultat", 40,   11,68,35,8, SS_LEFT, , 0
    CTEXT           "   Déci",  40,   11,76,35,8, SS_LEFT, , 0       
        
    
END

200 ICON MOVEABLE PURE LOADONCALL DISCARDABLE "ICON1.ICO"

Conclusion :


petit utilitaire sans prétention mais qui, je l'espère, pourra intéresser quelques uns.

Codes Sources

A voir également

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.