Algorithme de Cyclic Redundancy Chec (CRC)

Programmation d'applications complexes
Gratteur
Messages : 147
Inscription : ven. 22/avr./2005 23:02

Algorithme de Cyclic Redundancy Chec (CRC)

Message par Gratteur »

Voila, j'ai un petit problème avec l'algorithme de crc, logiquement ca devrait marcher mais allez savoir pourquoi il ne me rend pas le résultat souhaité (dans ce cas pour "IEND" : $AE426082)

Code : Tout sélectionner

Dim crc_table.l(256)
crc_table_computed = 0

Procedure make_crc_table()
  For n=0 To 255
    c = n
    For k=0 To 7
      If (c & 1)
        c = $edb88320 ! (c >> 1)
      Else
        c = c >> 1
      EndIf
    Next k
    crc_table(n) = c
  Next n
  crc_table_computed = 1
EndProcedure

Procedure update_crc(crc, *buf,len)
  c = crc
  If (~ crc_table_computed)
    make_crc_table()
  EndIf
  For n=0 To len-1
    c = crc_table((c ! PeekB(*buf+n)) & $ff) ! (c >> 8)
  Next n
  ProcedureReturn c
EndProcedure

Procedure crc(*buf, len)
  ProcedureReturn update_crc($ffffffff, *buf, len) ! $ffffffff
EndProcedure

*MemoryID = AllocateMemory(8*8) ; Pour les données (IEND)
    If *MemoryID
      PokeS(*MemoryID, "IEND")
      test = crc(*MemoryID, 4)
      debug hex(test)
      FreeMemory(*MemoryID)
    EndIf
Ca doit encore être une petite erreur à la con mais ce truc m'empêche de trouver le sommeil, quelqu'un peut m'aider ?
CameleonTH
Messages : 333
Inscription : sam. 25/juin/2005 11:18
Localisation : Laon (02)
Contact :

Message par CameleonTH »

Désoler je peut pas t'aider car moi et les algos j'y connais pas grand chose et encore moins pour le CRC :D
DSL
Avatar de l’utilisateur
Progi1984
Messages : 2659
Inscription : mar. 14/déc./2004 13:56
Localisation : France > Rennes
Contact :

Message par Progi1984 »

Gratteur
Messages : 147
Inscription : ven. 22/avr./2005 23:02

Message par Gratteur »

J'ai déja la doc qu'il me faut, mais j'ai trouvé l'erreur après une bonne nuit de sommeil : mes variables étaient signées, ce n'était pas très compatible avec le crc ;p
Dernière modification par Gratteur le jeu. 15/déc./2005 20:47, modifié 2 fois.
Dr. Dri
Messages : 2527
Inscription : ven. 23/janv./2004 18:10

Message par Dr. Dri »

La seule opération qui puisse poser probleme là dedans c'est le >>
Je vais regarder ce qu'on peut faire pour le virer ^^

[edit]

Code : Tout sélectionner

Dim crc_table.l(255)
crc_table_computed = 0

Procedure make_crc_table()
  For n=0 To 255
    c = n
    For k=0 To 7
      If (c & 1)
        c = $edb88320 ! ((c >> 1) & $7FFFFFFF)
      Else
        c = (c >> 1) & $7FFFFFFF
      EndIf
    Next k
    crc_table(n) = c
  Next n
  crc_table_computed = 1
EndProcedure

Procedure update_crc(crc, *buf,len)
  c = crc
  If crc_table_computed = 0
    make_crc_table()
  EndIf
  For n=0 To len-1
    t = (c >> 8) & $00FFFFFF
    c = crc_table((c ! PeekB(*buf+n)) & $ff) ! t
  Next n
  ProcedureReturn c
EndProcedure

Procedure crc(*buf, len)
  ProcedureReturn ~update_crc($ffffffff, *buf, len)
EndProcedure

*MemoryID = AllocateMemory(4) ; Pour les données (IEND)
If *MemoryID
  PokeS(*MemoryID, "IEND")
  test = crc(*MemoryID, 4)
  Debug Hex(test)
  FreeMemory(*MemoryID)
EndIf
Dri ;)
Gratteur
Messages : 147
Inscription : ven. 22/avr./2005 23:02

Message par Gratteur »

Arf oui c'est toi qui a raison Dr. Dri, merci d'avoir éclairé mon chemin vers la décadence et d'avoir redonné un sens à ma vie aussi rapidement ;p

Edit : pas bete le (c & $7FFFFFFF) pour masquer le premier 1 par un 0 après la division par 2 et récupérer un entier signé. Si vous avez des tests à faire avec des nombres binaires, faites attention au débuggeur et utilisez ceci : RSet(Right(Bin(a), 8), 8, "0"), en remplacant 8 par 8*nombre_d'octets.
Dernière modification par Gratteur le sam. 25/nov./2006 13:28, modifié 3 fois.
Dr. Dri
Messages : 2527
Inscription : ven. 23/janv./2004 18:10

Message par Dr. Dri »

@CameleonTH
Ce genre de remarque c'est pas vraiment utile...

@Gratteur
Si t'avais pas évoqué les nombres signés je n'aurai pas trouvé l'erreur, d'ailleurs c'est pour ca que je n'ai rien dit avant lol

Dri :lol:
Gratteur
Messages : 147
Inscription : ven. 22/avr./2005 23:02

Message par Gratteur »

Profitez bien de cet algorithme, il est pratique pour vérifier très rapidement qu'un fichier n'a pas été corrompu après un transfert, il suffit juste de recalculer les crc à l'ouverture du fichier et de les comparer avec les résultats stockés sur 4 octets pour chaque buffer à vérifier.
C'est très rapide et très efficace.
Frenchy Pilou
Messages : 2194
Inscription : jeu. 27/janv./2005 19:07

Message par Frenchy Pilou »

vérifier très rapidement qu'un fichier n'a pas été corrompu après un transfert
Et est-il vrai, que "les blindages" métalliques autour des Unités centrales, servent entres autres à artêter les rayons cosmiques ?
Pouvant entraîiner quelques dépolarisations ou autres...
Légendes urbaines ou réalité?
Dernière modification par Frenchy Pilou le dim. 18/déc./2005 22:37, modifié 1 fois.
Est beau ce qui plaît sans concept :)
Speedy Galerie
Gratteur
Messages : 147
Inscription : ven. 22/avr./2005 23:02

Message par Gratteur »

Réalité mais tu as plus de chances de gagner au loto.
Avatar de l’utilisateur
Flype
Messages : 2431
Inscription : jeu. 29/janv./2004 0:26
Localisation : Nantes

Message par Flype »

le crc est aussi utile pour vérifier si l'exécutable d'un programme n'a pas été cracké. c'est une des méthodes pour protéger un logiciel.

merci pour cet algo.
Image
Backup
Messages : 14526
Inscription : lun. 26/avr./2004 0:40

Message par Backup »

Frenchy Pilou a écrit :Et est-il vrai, que "les blindages" métalliques autour des Unités centrales, servent entres autres à artêter les rayons cosmiques ?
Pouvant entraîiner quelques dépolarisations ou autres...
Légendes urbaines ou réalité?

non c'est faux !! car rien n'arrete un Neutrino ! :)

la preuve dans les avions les portables ont souvent des problemes de ram
a cause des neutrinos , et avant de traverser la carlingue du portable , faut traverser celle de l'avion .....

de toute façon un neutrino traverse la Terre :)
Gratteur
Messages : 147
Inscription : ven. 22/avr./2005 23:02

Message par Gratteur »

Après quelques petits recherches voici ce que je peux en dire :

- Les rayons cosmiques sont composé à 85% des protons, à 14% des noyaux d'Hélium et à 1% des électrons (et parfois autres).

- La profondeur de pénétration est d'autant plus grande que la masse de la particule est grande, que la vitesse est élevée et que la charge est plus faible, et comme :
* Le proton a une masse environ 200 fois plus grande que celle de l'électron donc le proton pénètre plus profondément que l'électron à vitesse égale.
* Le noyau d'hélium à une masse 4 fois plus grande que le proton et compte deux charges électriques : à vitesse égale le noyau d'hélium penètre plus profondémment que le proton.

- L'Hélium est donc la particule qui pénètre le plus profondément, or :
* Les noyaux d'hélium ont une très faible pénétration dans la matière et sont souvent arrêtés par 10 cm d'air ou une feuille de papier.

- On peut donc consiédrer que le blindage métallique est utile pour arreter la plupart des rayons cosmiques qui arrivent jusqu'à nous (au final tout dépend surtout de leur vitesse).
Dr. Dri
Messages : 2527
Inscription : ven. 23/janv./2004 18:10

Message par Dr. Dri »

Je viens de me rendre compte qu'il y a déjà une fonction native pour calculer le CRC... Mais pas dans un fichier, alors je l'ai codé en partant de ce qui avait été fait au dessus

Code : Tout sélectionner

Structure Bytes
  b.b[0]
EndStructure

#CRC32_BufferLength = 2048

Dim    CRC32_Table.l($FF)
Global CRC32_TableComputed.l

Procedure CRC32_MakeTable()
  Protected i.l, j.l, crc.l
  
  For i = 0 To $FF
    crc = i
    
    For j = 1 To 8
    
      If crc & 1
        crc = $EDB88320 ! ((crc >> 1) & $7FFFFFFF)
      Else
        crc = (crc >> 1) & $7FFFFFFF
      EndIf
      
    Next j
    
    CRC32_Table(i) = crc
  Next i
  
  CRC_TableComputed = #True
EndProcedure

Procedure CRC32_Update(crc.l, *buffer.Bytes, Length.l)
  Protected i.l
  
  If CRC32_TableComputed = #False
    CRC32_MakeTable()
  EndIf
  
  While i < Length
    crc = CRC32_Table((crc ! *buffer\b[i]) & $FF) ! ((crc >> 8) & $00FFFFFF)
    i + 1
  Wend
  
  ProcedureReturn crc
EndProcedure

Procedure CRC32_Fingerprint(*buffer.l, Length.l)
  ProcedureReturn ~CRC32_Update($FFFFFFFF, *buffer, Length)
EndProcedure

Procedure CRC32_FileFingerprint(Filename.s)
  Protected crc.l, File.l, Buffer.l, Offset.l, Length.l
  
  File = ReadFile(#PB_Any, Filename)
  If File
    Buffer = AllocateMemory(#CRC32_BufferLength)
    
    If Buffer
      Length = Lof()
      crc = $FFFFFFFF
      
      While (Length - Offset) > #CRC32_BufferLength
        ReadData(Buffer, #CRC32_BufferLength) 
        crc = CRC32_Update(crc, Buffer, #CRC32_BufferLength)
        Offset + #CRC32_BufferLength
      Wend
      
      If Length > Offset
        Length - Offset
        ReadData(Buffer, Length)
        crc = CRC32_Update(crc, Buffer, Length)
      EndIf
      
      FreeMemory(Buffer)
    EndIf
    
    CloseFile(File)
  EndIf
  
  ProcedureReturn ~crc
EndProcedure
(j'ai vérifié le CRC de mes fichiers avec quickzip et ca semble foncionner ^^)

Dri ;)
Répondre