Télécharger le zip
J'allais le faire =), pour ceux que ca interesse une version en C qui encode et decode c'est ici: http://Neo_Fr.fr.nf/Bin2Hex.zipNeo_Fr
En fait, cette source aurait plus sa place dans la partie "assembler"... Ce n'est plus du C, si ?
Ça ferais un excellent snippet :P Bon certains aurait de l'urticaire a cause de l'ASM mais tant qu'a avoir du code aussi bien qu'il soit optimisé.
MAX12: tout-à-fait d'accord, mais sur un code qui ne fait que transformer une chaîne de caractères en hexadécimal, je ne vois pas bien où se situe la gain par rapport au C classique...J'approuve aussi ta note, parce que techniquement, c'est le top ! Mais je ne vois pas bien l'utilité...J'utilise aussi parfois l'ASM (bien que rarement), mais pas directement dans le code C (ou C++, que j'utilise plus).Allez, je vais aussi mettre une excellente note, parce que ce n'est pas la première fois que je vois des codes de BruNews, j'ai vu pas mal de ses commentaires et conseils, et je dois dire que je ne connais PERSONNE qui code aussi bien et aussi proprement. Je rêverai d'avoir des collègues comme lui ;o) Au moins, j'apprendrais pas mal de choses, je pense, contrairement aux développeurs chez le client chez qui je suis pour l'instant, qui me font recoder pas mal de choses (code qui fonctionne), simplement parce que, malgré les commentaires, ils ne comprennent rien... Alors, si je mettais de l'ASM... Ils m'ont demandé ce que c'était une classe et un objet, parce que j'en ai parlé dans des specs. Ils n'avaient jamais entendu ce terme...Bon, j'arrête de causer... Je suis trop bavard... ;o)Bonne continuation !
Je tente d'utiliser ta fonction assembleur pour convertir une chaine en code hexa, mais il semble y avoir un soucis.__declspec(naked) char* __fastcall bnStrToHex(char *szsrc, char* szdst)Mon projet est une application MFC sous VS2003.lorsque je passe mon parametre szsrc, alloué et renseigné juste avant l'appel, son contenu est "dégradé", au point qu'un delete juste apres l'appel a bnStrToHex fait tout explosé.Qu'ais-je bien pu oublier ?exemple : char* pHexStr = new char[size*2+1]; char* bufferCpy = new char[size]; ::memcpy( bufferCpy, buffer, size ); // buffer est renseigné plus tot dans le code bnStrToHex( bufferCpy, pHexStr );// delete bufferCpy; // fait tout crasher // bufferCpy = NULL;merci.
à tester: delete [] bufferCpy;
Ca ne change rien, il y a un probleme d'allocation sur le heap.Mais le contenu de la memoire est etrange.Je pense que l'attribut "naked", dixit la doc : enleve le prologue et l'epilogue de la fonction, fais que la fonction assembleur est directement executé au coeur même de la fonction appelante ( en clair a la compilation cela ne forme qu'un bloc ), par contre je ne connais pas l'influence du _fastcall.La doc dis :The __fastcall calling convention specifies that arguments to functions are to be passed in registers, when possible. The following list shows the implementation of this calling convention.Le probleme est donc et lorsque ce n'est pas possible ??! :sEt pourquoi mon delete crash et pourquoi j'ai une heap exception ? ><'' Y a t'il une methode ALL C/C++ qui pourrait me faire la même chose, car bien que le resultat attendue soit correct, ca bug dans mon code quand même :/
Les params passent en registre (ECX et EDX) à tout coup pour cette fonction, le prob ne peut pas venir de cela.'naked' ne spécifie pas 'inline' donc pas d'exécution DANS l'appelant. Il empêche simplement le compilo d'y toucher (prologue, épilogue et autres arguties).Dans tous les cas, faut trouver le prob dans ton code appelant. J'ai ce genre de fonction qui tourne en prod sur de gros serveurs depuis fort longtemps sans l'ombre d'un soucis.
En fait je genere un .reg à partir de plusieurs informations. T'as methode est donc utile pour creer une clef du genre :"BB1"=hex:fc,03,d0,ac,05,89,47,d0,fe,62,00,2e,fa,64,82,20 Lorsque je debogue, quelque chose m'intrique, c'est que la le parametre szsrc n'a rien a voir avec le pointeur que je lui ai passé ... Soit le parametre bufferCpy qui est passé à ta methode.Je te donne un exemple qui reproduit le crashj'ai crée un simple projet console avec VS2003.//***********************************************************************************//#include <stdio.h>#include <stdarg.h>#include <ctime>#include <string>#include <tchar.h>#include <map>#include <set>#include <assert.h>#include <typeinfo.h>#include <fstream>#include <sstream>__declspec(naked) char* __fastcall bnStrToHex(char *szsrc, char* szdst){ // ECX = szsrc, EDX = szdst __asm { mov [esp-4], esi mov esi, ecxfromSRC: mov al, [esi] test al, al je short strEXIT mov cl, al add edx, 2 and cl, 15 shr al, 4 add cl, 48 add al, 48 cmp cl, 57 jbe short L1 add cl, 7L1: cmp al, 57 jbe short L2 add al, 7L2: add esi, 1 mov byte ptr[edx-2], al mov byte ptr[edx-1], cl jmp short fromSRCstrEXIT: mov byte ptr[edx], 0 mov esi, [esp-4] mov eax, edx ret 0 }}std::string string_hex( const char* buffer, const size_t& size ){ char* pHexStr = new char[size*2+1]; char* bufferCpy = new char[size]; ::memcpy( bufferCpy, buffer, size ); bnStrToHex( bufferCpy, pHexStr ); // TODO !! // Attention il faut deleter pHexStr et BufferCpy !!!! (&*pHexStr)[size*2] = '\0'; std::ostringstream oss; //initialise un string stream qui stock la sortie de std::hex unsigned int i = 0; for ( char* c = pHexStr; i < size*2; i++ ) { if ( i != 0 ) oss << _T(","); oss << c[i]; oss << c[++i]; } return oss.str();}int _tmain(int argc, _TCHAR* argv[]){ try { std::fstream stream( "C:\\Config.reg", std::ios_base::binary | std::ios_base::out | std::ios_base::trunc ); std::string header = _T("Windows Registry Editor Version 5.00\n"); stream.write( header.c_str(), header.size() ); header = _T("\n"); stream.write( header.c_str(), header.size() ); std::string agentKey = _T("[HKEY_LOCAL_MACHINE\\SOFTWARE\\Medialive\\Agent]\n"); stream.write( agentKey.c_str(), agentKey.size() ); std::ostringstream version; version << _T("\"Version\"=\"") << "3.1" << _T("\"\n"); stream.write( version.str().c_str(), version.str().size() ); std::ostringstream bbpath; bbpath << _T("\"BBPath\"=\"") << "C:\\azerty.bb" << _T("\"\n"); stream.write( bbpath.str().c_str(), bbpath.str().size() ); std::ostringstream agentPath; agentPath << _T("\"MedialiveAgent\"=\"") << "C:\\azerty.dll" << _T("\"\n"); stream.write( agentPath.str().c_str(), agentPath.str().size() ); std::ostringstream gbbKey; gbbKey << _T("\"BB1\"=hex:") << string_hex ( "_Ahryman__40000_", 16 ) << _T("\n"); stream.write( gbbKey.str().c_str(), gbbKey.str().size() ); std::ostringstream gbbChecksum; gbbChecksum << _T("\"BB2\"=hex:") + string_hex ( "_Ahryman__40000_", 16 ) << _T("\n"); stream.write( gbbChecksum.str().c_str(), gbbChecksum.str().size() ); std::string initKey = _T("\"InitialKey\"=hex:00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00\n"); stream.write( initKey.c_str(), initKey.size() ); std::string defaultId = _T("\"DefaultID\"=hex:00,00,00,00\n"); stream.write( defaultId.c_str(), defaultId.size() ); stream.close(); } catch( ... ) { assert ( false ); } return 0;}//************************************************************************************//
Si tu me mets tout cela en PSEUDO code avec exemple de ce qu'il faut obtenir, je te le refais en vrai code (plus de stream, string et autres couches d'interprétation qui ont peu à faire dans du Windows).
OK j'ai décortiqué tout ce sabir, je te fais cela.
Windows Registry Editor Version 5.00[HKEY_LOCAL_MACHINE\SOFTWARE\Medialive\Agent]"Version"="3.1""BBPath"="C:\azerty.bb""MedialiveAgent"="C:\azerty.dll""BB1"=hex:string_hex("_Ahryman__40000_", 16)"BB2"=hex:string_hex("_Ahryman__40000_", 16)"InitialKey"=hex:00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00"DefaultID"=hex:00,00,00,00CODE POUR OBTENIR CELA:const char szREGEDIT[] = "Windows Registry Editor Version 5.00\r\n\r\n"; // len = 40const char szHKLMMDLV[] = "[HKEY_LOCAL_MACHINE\\SOFTWARE\\Medialive\\Agent]\r\n"; // len = 47const char szVERSION31[] = "\"Version\"=\"3.1\"\r\n"; // len = 17const char szBBPATH[] = "\"BBPath\"=\"C:\\azerty.bb\"\r\n"; // len = 25const char szMDLV[] = "\"MedialiveAgent\"=\"C:\\azerty.dll\"\r\n"; // len = 34const char szBB1HEX[] = "\"BB1\"=hex:";int __stdcall FaireFichierReg(){ HANDLE hfl; char szhex[36], buf[100], *c, *d; DWORD v, i; hfl = CreateFile("D:\\Config.reg", GENERIC_WRITE, 0, 0, CREATE_ALWAYS, 0, 0); if(hfl == INVALID_HANDLE_VALUE) return 0; WriteFile(hfl, szREGEDIT, 40, &v, 0); WriteFile(hfl, szHKLMMDLV, 47, &v, 0); WriteFile(hfl, szVERSION31, 17, &v, 0); WriteFile(hfl, szBBPATH, 25, &v, 0); WriteFile(hfl, szMDLV, 34, &v, 0); bnStrToHex("_Ahryman__40000_", szhex); // 1 SEULE FOIS, SORT 32 OCTETS ICI c = (char*) szBB1HEX; d = buf; while(*d = *c) {d++; c++;} // RECOPIE, d EST POINTEUR D'ECRITURE c = szhex; i = 16; // strlen("_Ahryman__40000_") do { // COPIE DE 2 OCTETS DE szhex A CHAQUE TOUR *d++ = *c++; *d++ = *c++; *d++ = ','; } while(--i); *(d-1) = '\r'; // ON SORT AVEC 1 VIRGULE EN TROP, ON ECRASE *d++ = '\n'; WriteFile(hfl, buf, d - buf, &v, 0); // POUR BB2 QUI EST IDEM buf[3] = '2'; WriteFile(hfl, buf, d - buf, &v, 0); // JE STOPPE ICI, LE RESTE EST TRIVIAL ET DEJA FAIT PLUS HAUT return CloseHandle(hfl);}En quoi est-ce plus compliqué de coder un peu ?Quand on réalise qu'on peut tout maitriser et qu'il y a énorme benef de perfs et taille code, il n'y a plus à se poser la question.
OUPS, c'estWindows Registry Editor Version 5.00[HKEY_LOCAL_MACHINE\SOFTWARE\Medialive\Agent]"Version"="3.1""BBPath"="C:\azerty.bb""MedialiveAgent"="C:\azerty.dll""BB1"=hex:5F,41,68,72,79,6D,61,6E,5F,5F,34,30,30,30,30,5F"BB2"=hex:5F,41,68,72,79,6D,61,6E,5F,5F,34,30,30,30,30,5Fqu'on obtient avec code plus haut.
Merci, grace à ton exemple j'ai mis en evidence le probleme avec ta methode bnStrToHex.Le premier exemple provient de ton exemple et fonctionne //*******************************************************************//char* szhex = new char[36];char* buf = new char[100];bnStrToHex("_Ahryman__40000_", szhex); // 1 SEULE FOIS, SORT 32 OCTETS ICI delete[] szhex;delete[] buf;//*******************************************************************//Celui-ci est pratiquement identique mis a part le fait que je ne passe pas une chaine constante mais un pointeur contenant ma chaine:*******************************************************************//char* szhex = new char[36];char* bufferCpy = new char[16]; ::memcpy( bufferCpy, "__Ahryman_40000_", 16 );bnStrToHex( bufferCpy, szhex ); // Ici ma chaine n'est pas terminée par '\0' d'ou le crash !!! J'ai donc besoin d'un tableau de taille 17 et d'inserer le caractere de fin de chaine.delete[] bufferCpy; delete[] szhex;Donc finalement pour que cela fonctionne correctement, il faut appeler la methode comme suis en s'assurant que le parametre d'entrée est bien une chaine avec caractere de fin.//************************************************************************************//char* szhex = new char[36];char* bufferCpy = new char[17]; ::memcpy( bufferCpy, "_Ahryman__40000_", 17 );bufferCpy[16] = '\0';bnStrToHex( bufferCpy, szhex );delete[] bufferCpy; // ca ne pete plus -_-''delete[] szhex;J'ai donc une derniere question à te poser, mon besoin final est d'avoir la même methode bnStrToHex prenant en plus la taille de la chaine que je veux traiter (plutot que de s'arreter au caracetre de fin de chaine). Dans mon prog bufferCpy pourra contenir en plein milieu ce caractere de fin de chaine, car c'est une valeur sur 16 caracteres generée aleatoirement. Or j'ai besoin de recuperer le code hexa de l'integralité de ces caracteres.Merci.
Prend la taille du buffer en parametre:void __stdcall Bin2Hex(BYTE* lpIn, DWORD dwInSize, BYTE* lpOut){ static const BYTE HexaTable[16] = { 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66 }; DWORD i = (dwInSize-1); while(1) { lpOut[2*i] = HexaTable[(lpIn[i] >> 4) & 0x0F]; lpOut[2*i+1] = HexaTable[(lpIn[i]) & 0x0F]; if(!i--) break; }}Neo_Fr
A TESTER mais devrait aller:__declspec(naked) char* __fastcall bnStrToHex(char *szsrc, char* szdst, DWORD lensrc){ // ECX = szsrc, EDX = szdst, [esp+4] = lensrc __asm { mov [esp-4], esi mov [esp-8], ebx mov esi, ecx mov ebx, [esp+4]fromSRC: mov al, [esi] mov cl, al add edx, 2 and cl, 15 shr al, 4 add cl, 48 add al, 48 cmp cl, 57 jbe short L1 add cl, 7L1: cmp al, 57 jbe short L2 add al, 7L2: add esi, 1 mov byte ptr[edx-2], al mov byte ptr[edx-1], cl sub ebx, 1 jne short fromSRCstrEXIT: mov byte ptr[edx], 0 mov esi, [esp-4] mov ebx, [esp-8] mov eax, edx ret 4 }}ATTENTION que je ne teste pas si lensrc > 0 en entrée.
Ha bein oui nickel,ca marche tres bien ca.Merci ^^
Se souvenir du profil
Mot de passe oublié ? / Activation de compteCréer un compte