Comment réduire l'espace de code d'une conversion de caractères ASCII hexadécimale à l'aide d'un petit espace de code fort> strong>
dans une application intégrée, j'ai un espace limité extraordinaire (note 1). J'ai besoin de convertir des octets, de l'E / S série, avec les valeurs ASCII "0" à "9" et "A" à "F" aux valeurs hexadécimales habituelles 0 à 15. Aussi toutes les 240 combinaisons, y compris ' a 'à' f ', doit être détecté (comme une erreur). p>
Fonctions de la bibliothèque telles que La vitesse n'est pas un problème. La taille du code est le facteur limitant. P> Ma méthode actuelle recélère les codes de 256 octets en 256 codes tels que '0' à '9' et 'A' à 'Z' ont les valeurs 0 - 35. Toutes idées sur la manière de réduire ou de réduire les approches différentes sont appréciées. Strong> p> Note 1: 256 Les instructions sont disponibles pour le code et les données constantes (1 Données d'octets coûte 1 instruction) dans une mémoire protégée PIC pour un chargeur de démarrage. Ce code coûte ~ 10 instructions. Current AP a besoin d'une nouvelle écriture et d'une seule instruction de rechange, Notes: PIC16. Je préfère coder dans 'C', mais doit faire ce qu'il faut. Le code de montage suit. Une réponse rapide n'est pas requise. P> [modifier Scanf (), ATOI (), Strtol () code> sont Loin em> trop grand à utiliser. P>
Optimisation de la solution existante comme suggéré par @gJ. En C, effectuer le ch + = 7; ch & = (~ 64); code> au lieu de
ch = (ch + 7) & (~ 64); code> 1 instruction enregistrée. Aller à l'assemblage sauvegardé un autre en ne faisant pas recharger
ch code> dans le
si () code>. P> p>
3 Réponses :
Peut-être utiliser ctype.h's isxdigit () code>
:
ch -= (ch >= 'A') ? ('A' - 10) : (ch >= '0') ? '0' : 0 ; if( ch > 0xf ) { // handle error }
Cela devrait-il être ('A' - 10) plutôt que ('A' + 10) puisque vous soustrayez cette quantité de CH?
Merci - depuis isxdigit () code> retourne true sur
A code> à
f code> ',
ch code> prend les valeurs 42 à 47 . Je suppose qu'un
si () code> pourrait être ajouté. En supposant que
isxdigit () code> n'est pas une zone de grande recherche, il utilise probablement 3
si () code> s.
@chux: Je ne suis pas sûr de ce que vous voulez dire, le résultat en ch code> sera de 0 à 15 selon les besoins. La transformation est effectuée si le chiffre est hexadécimal. Étant donné que
isxdigit () code> est probablement une macro, vous pouvez trouver sa définition complète dans ctype.h.
@chux: J'ai ajouté une alternative qui n'utilise pas isxdigit () code> mais qui modifie
ch code> même s'il n'est pas un chiffre hexagonal.
isxdigit () code> retourne vrai sur 0-9, A-F et A-F. La 1ère solution convertit
ch code> de 'A' en 10, bien, mais convertit 'a' en 42 et n'est pas détecté transmis à l'erreur // poignée. La deuxième solution convertit ':' à '?' en 10 à 15 et ils ne sont pas détectés dans l'erreur // de la poignée.
Mon isxdigit () code> est en effet une macro:
#define isxdigit (x) isamong (x, "0123456789abcdefabcdef") code>. Certainement plus de 10 instructions. BTW, plus tard, je serai dans le désert pendant quelques jours.
@Clifford si (ch <0x0 .. code> ne peut jamais être vrai pour un caractère non signé
@chux: Votre question indique clairement '0' à '9' et 'A' à 'F'. J'ai simplement suivi votre spec.
@JEB: vrai - encore mieux.
@chux: Je suis épais, je vois ce que tu veux dire sur A à F. Il a besoin d'un test Islower () code> mais la solution est de plus en plus insatisfaisante peut-être. Une solution consiste à convertir des minuscules en majuscules avant la transformation et accepter des chiffres hexagonales minuscules
ch & = 0x20 code>.
La famille PIC16 est RISC McPu, vous pouvez donc essayer d'optimiser votre code ASM. Ceci est votre code ASM C compilateurs C ...
call GetData //if GetData return result in WREG then you do not need to store in ch and read it again! // movwf ch // movf ch, w addlw 0x100 - '0' - 10 //if (((WREG -= ('0' + 10)) < 0) || ((WREG -= ('A' - '0' - 10)) >= 0)) { btfss STATUS, 0 goto DoAddx addlw 0x100 - ('A' - '0' - 10) btfsc STATUS, 0 DoAddx addlw 10 //WREG += 10; } movwf ch //ch = WREG; addlw 0x100 - 0x10 //if (WREG > 15) { btfsc STATUS, 0 //Check carry goto HandleError
Est BTFSC WRREG, 6 CODE> Valable sur un PIC16?
@D Krueger: WRREG est accessible uniquement sur New Pic16 et Pic12 McPus marqué comme technologie XLP. WRREG est une copie du registre de travail alu à l'adresse 0x09.
@Krueger: a ajouté également une version compatible avec l'ancien PIC16 MCPUS.
Merci. Dans C code>, effectuant le
ch + = 7; ch & = (~ 64); code> au lieu de
ch = (ch + 7) & (~ 64); code> 1 instruction enregistrée. Aller à l'assemblage sauver une autre.
@chux: Vérifiez aussi mon édition III Explication :)
Avec une optimisation de la bonne compilation, cela peut prendre moins d'espace de code:
unsigned char ch = GetData(); // Fetch 1 byte of incoming data; if (((ch += 0xC6) & 0x80) || !((ch += 0xF9) & 0x80)) { ch += 0x0A; } if (ch > 15) { ; // handle error }
Ce code n'est pas correct! Quel devrait être le résultat si l'entrée est le caractère @ (0x40)?
@ Gj.if sur l'entrée ch == 0x40 code> alors sa valeur finale sera
0xff code>, qui sera capturé par le
(ch> 15) code> test.
Merci. Ma meilleure utilisation de votre réponse et de vos variations était encore +0 instruction sur l'original. (Cela comporte 3 branches par rapport à l'original 2.) Il a fallu un certain temps pour comprendre votre approche élégante, mais elle ouvre une pensée.