IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Assembleur Discussion :

Calcul de crc16


Sujet :

Assembleur

  1. #1
    Membre confirmé Avatar de bifur
    passe le balais et l'aspirateur
    Inscrit en
    Mars 2008
    Messages
    314
    Détails du profil
    Informations personnelles :
    Âge : 38

    Informations professionnelles :
    Activité : passe le balais et l'aspirateur

    Informations forums :
    Inscription : Mars 2008
    Messages : 314
    Points : 550
    Points
    550
    Par défaut Calcul de crc16
    Bonjour, je suis en train d'essayer de faire un logiciel qui permettrait de visionner certaines valeurs contenues dans des appareils sur un réseau modbus.

    Pour faire cela, il faut envoyer des trames (dont je connais le format) par liaison série et, là ou je butte un peu, c'est sur le calcul du crc, chose indispensable car sinon les trames sont considérées comme corrompues.

    J'ai trouvé une doc intéressante sur ce site mais je n'arrive pas à mettre tout ça en place : http://dvsoft.developpez.com/Articles/CRC/

    J'ai trouvé un petit truc sur internet qui me permet de verifier mes expérimentations :
    http://sitelec.org/cours/abati/flash/crc16.swf

    J'ai essayé de mettre en place bêtement les divers algos que j'ai pu trouver sur le net sans arriver à faire quelque chose qui fonctionnait; j'ai même fait une routine qui divisait par le polynôme et qui ne gardait que le reste de l'opération.

    J'aimerais savoir si quelqu'un a déja fait une sorte de sous-routine pour calculer la valeur CRC pour une trame (avec les paramètres modbus ou autre) en Assembleur; si oui, j'aimerais avoir les docs qui vous ont permis de faire ça.

  2. #2
    Membre averti Avatar de Pierre Maurette
    Profil pro
    Inscrit en
    Juillet 2002
    Messages
    283
    Détails du profil
    Informations personnelles :
    Âge : 68
    Localisation : France

    Informations forums :
    Inscription : Juillet 2002
    Messages : 283
    Points : 390
    Points
    390
    Par défaut
    Bonjour,
    L'algo du lien est imprécis (il serait plus clair d'écrire octet à traiter = premier octet au départ, puisque octet suivant = premier octet pousse à créer une variable octet suivant) et faux (c'est un < et non un <= dans le TANT QUE).
    Je l'ai prototypé en C (et d'ailleurs, pourquoi l'assembleur ?), ça donne les mêmes résultats que le lien, reste à savoir s'ils sont bons :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    #include <stdio.h>
    #include <stdlib.h>
    #include <stdint.h>
     
    uint16_t calcule_crc(uint8_t* octets, int nboctets) {
    	uint16_t crc = 0xFFFF;
    	int i, done = 0;
    	uint8_t todo;
    	if (nboctets != 0) {
    		do {
    			todo = octets[done];
    			crc ^= todo;
    			for (i = 0; i < 8; i++) {
    				if (crc % 2 != 0) {
    					crc = (crc >> 1) ^ 0xA001;
    				} else {
    					crc = crc >> 1;
    				}
    			}
    			done++;
    		} while (done < nboctets);
    	}
    	return crc;
    }
     
    int main(void) {
    	uint8_t octets[] = {0x06, 0xAC, 0x45, 0x2B, 0x11};
    	uint16_t crc = calcule_crc(octets, sizeof octets / sizeof octets[0]);
    	printf("Pf: %02X  PF: %02X\n", crc & 0x00FF, crc >> 8);
    	return EXIT_SUCCESS;
    }
    Attention, un 0xFFFF en retour est signe d'erreur. Pas très fûté, puisque c'est une valeur possible. Il y a d'autres solutions.

  3. #3
    Membre confirmé Avatar de bifur
    passe le balais et l'aspirateur
    Inscrit en
    Mars 2008
    Messages
    314
    Détails du profil
    Informations personnelles :
    Âge : 38

    Informations professionnelles :
    Activité : passe le balais et l'aspirateur

    Informations forums :
    Inscription : Mars 2008
    Messages : 314
    Points : 550
    Points
    550
    Par défaut
    pourquoi en assembleur?
    tout simplement parce que je ne comprend pas le C (ou très peu)

    si votre algo donne les même résultat que le programme de démo ça ne m'étonne pas trop, je pense que c'est le bon algo qui permettent de calculer le crc car j'avait aussi trouvé deux autres doc qui semblait me donner le même algo:
    http://bofur.olympe-network.com/img/crc16.jpg
    http://bofur.olympe-network.com/img/crc16fr.jpg

    pouvez vous me traduire "crc = (crc >> 1) ^ 0xA001" en langage assembleur parce que je comprend pas (et je me demande si mon erreur ne vient pas de la)

  4. #4
    Membre averti Avatar de Pierre Maurette
    Profil pro
    Inscrit en
    Juillet 2002
    Messages
    283
    Détails du profil
    Informations personnelles :
    Âge : 68
    Localisation : France

    Informations forums :
    Inscription : Juillet 2002
    Messages : 283
    Points : 390
    Points
    390
    Par défaut
    Voilà, j'ai passé la fonction en assembleur x86 (NASM, Linux, 32bit):
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    		section .text
     
        global  calcule_crc
     
    calcule_crc:
    	push ebp
    	mov  ebp, esp
     
    	mov  ax, -1
    	cmp  dword[ebp+12], 0		;nboctets
    	jz   fin
    	mov  edi, [ebp+8]
     
    boucleoctets:
    	xor  al, [edi]			;crc = crc xor l'octet
     
    	mov  ecx, 8
    boucle8fois:
    	shr  ax, 1				;le LSB tombe dans le CF
    	jnc  .1
    	xor  ax, 0xA001
    .1
    	loop boucle8fois			;fin boucle8fois
     
    	inc  edi				;adresse nouvel octet
    	dec  dword[ebp+12]
    	jnz  boucleoctets			;fin boucleoctets
     
    fin:
    	leave
            ret
    On ne retrouve pas tout à fait l'algo et donc le code C, puisque le shr a la bonne idée de faire tomber le bit de poids faible dans le carry. Le programme C pour le tester:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    #include <stdio.h>
    #include <stdlib.h>
    #include <stdint.h>
     
    uint16_t calcule_crc(uint8_t* octets, int nboctets);
     
    uint16_t calcule_crc_c(uint8_t* octets, int nboctets) {
    	uint16_t crc = 0xFFFF;
    	int i, done = 0;
    	uint8_t todo;
    	if (nboctets != 0) {
    		do {
    			todo = octets[done];
    			crc ^= todo;
    //			break;
    			for (i = 0; i < 8; i++) {
    				if (crc % 2 != 0) {
    					crc = (crc >> 1) ^ 0xA001;
    				} else {
    					crc = crc >> 1;
    				}
    			}
    			done++;
    		} while (done < nboctets);
    	}
    	return crc;
    }
     
    int main(void) {
    	uint8_t octets[] = {0xA1, 0x28, 0x33, 0x4C, 0xF5};
    	uint16_t crc = calcule_crc(octets, sizeof octets / sizeof octets[0]);
    	printf("Ce programme est en mode %d bit\n", sizeof(char*) == 8 ? 64 : 32);
    	printf("(A) Pf: %02X  PF: %02X\n", crc & 0x00FF, crc >> 8);
    	crc = calcule_crc_c(octets, sizeof octets / sizeof octets[0]);
    	printf("(C) Pf: %02X  PF: %02X\n", crc & 0x00FF, crc >> 8);
    	return EXIT_SUCCESS;
    }

  5. #5
    Membre confirmé Avatar de bifur
    passe le balais et l'aspirateur
    Inscrit en
    Mars 2008
    Messages
    314
    Détails du profil
    Informations personnelles :
    Âge : 38

    Informations professionnelles :
    Activité : passe le balais et l'aspirateur

    Informations forums :
    Inscription : Mars 2008
    Messages : 314
    Points : 550
    Points
    550
    Par défaut
    merci pour cette réponse et désolé de n'avoir pas répondu plus tôt j'etais tres occupé

    grâce a vous j'ai put développer une fonction qui me permet de calculer tout les crc16 (il suffit pour ça de modifier la valeur initiale du crc et/ou le polynome)

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    calcrc16:  ;ds:esi=d‚but de la chaine
               ;ecx=Nb d'octet de la chaine
               ;ax=valeur initiale du CRC
               ;dx="polynome"
    boucl:
    xor al,[esi]
     
    shr ax,1
    jnc no1
    xor ax,dx
    no1:
    shr ax,1
    jnc no2
    xor ax,dx
    no2:
    shr ax,1
    jnc no3
    xor ax,dx
    no3:
    shr ax,1
    jnc no4
    xor ax,dx
    no4:
    shr ax,1
    jnc no5
    xor ax,dx
    no5:
    shr ax,1
    jnc no6
    xor ax,dx
    no6:
    shr ax,1
    jnc no7
    xor ax,dx
    no7:
    shr ax,1
    jnc no8
    xor ax,dx
    no8:
    inc esi
    dec ecx
    jnz boucl
    ret
    en plus il me semble qu'en remplaçant ax et dx par eax et edx on peut faire du crc32, a votre avis?

    j'ai trouvé mes erreurs par rapport a mes précédente fonctions que j'ai essayé de developper: je fesait un shl au lieu d'un shr, pourquoi shl au lieu de shr? et ce même si c'était expliqué clairement? parce que j'ai mal comprit le cours http://dvsoft.developpez.com/Articles/CRC/ et je souhaitait faire une sorte de division binaire pour arriver a calculer le crc

    je ne croit pas encore avoir comprit totalement comment fonctionnait le crc mais je peut au moins le calculer

  6. #6
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Janvier 2011
    Messages
    33
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2011
    Messages : 33
    Points : 25
    Points
    25
    Par défaut
    Bonjours a tous alors voila je viens de tomber sur cette discussion qui m'interresse beaucoup.
    Car en fait j'ai besoin de faire une laison Modbus RTU et jai donc besoin de calculer le CRC16 Mais mon plus gros soucis étant que je dois le faire en PIC Basic (pour un pic qui est le PB-3B)

    Et donc est-ce que quelqu'un saurait s'y prendre ?

    Merci d'avance

  7. #7
    Candidat au Club
    Profil pro
    Inscrit en
    Février 2011
    Messages
    3
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2011
    Messages : 3
    Points : 2
    Points
    2
    Par défaut
    Bonjour je suis un débutant en assembleur. Je parviens à comprendre les concepts de base, mais j'ai tout de même certaines difficultés à coder.
    Je dois réaliser une fonction qui calcule le CRC-16 d'un tableau en utilisant la convention CRC-CCITT. Les paramètres de la fonction doivent être passés par la pile (stack).

    Il n'y a aucun passage de paramètres par les registres (AX,BX,CX, ETC...)

    Sans nécessairement avoir le code complet, j'aimerais que vous m'aidiez à cibler ce que j'ai à faire pour coder cette fonction. J'aimerais aussi savoir comment fonctionnent les boucles en assembleur 8086.

    Merci et bonne journée!

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. [9iR1] Calcul CRC16 et 32
    Par langenfeld dans le forum PL/SQL
    Réponses: 4
    Dernier message: 13/06/2013, 13h34
  2. [PHP 5.0] Calcul CRC16 PHP
    Par sionib dans le forum Langage
    Réponses: 1
    Dernier message: 24/10/2012, 10h50
  3. Calcul CRC16 en c#
    Par petitours dans le forum C#
    Réponses: 2
    Dernier message: 05/09/2011, 23h34
  4. calcul d'un crc16 (polynome 0x1021)
    Par sanatou dans le forum C++
    Réponses: 8
    Dernier message: 12/01/2007, 13h32
  5. [TP7] Calculer sin, cos, tan, sqrt via le FPU
    Par zdra dans le forum Assembleur
    Réponses: 8
    Dernier message: 25/11/2002, 04h09

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo