Test de compilo !

Test de compilo ! - C++ - Programmation

Marsh Posté le 01-11-2002 à 13:30:23    

Jouons avec nos amis les compilo [:dawa]
Pour résumer la situation, je suis en train de faire un chiti compilo. Le bougre compile de l'asm en run-time qu'il est ensuite possible d'executer. Je m'interrogeais, car avec des exemples un *peu* long (genre 10lignes :D) toute la procedure de compilation commencait a prendre du temps. J'ai donc eu l'idée de faire un bon profiling des familles (cad a grand coup de GetTickCount()/printf()) pour savoir quelle était la partie prenant le plus de temps. Et oh, suprise, une variable contenant le temps écoulé pour une phase prenait des valeurs saugrenues (genre 1577451). Et ceci rien qu'en release. Comme je craignais un sale effet de bord du code généré par mon compilo, j'ai entrepris des recherches. En fait, VC++ digere tres mal l'appel a mon code compilé, c a d qu'il ne prends pas gaffe au fait que mon "call exec" peut tres bien sacager les valeurs de certains registres. Résultat, la variable contenue dans ebx etait écrasée par mon code, mais visu continuait de l'utiliser comme si de rien n'était. Histoire de rigoler, je vous propose ce petit test pour savoir si ca fait ca aussi avec d'autre compilo que VC++ .NET :
 
 
 
 

Code :
  1. #include <windows.h>
  2. //code a executer. Met une valeur bidon dans eax,ebx,ecx et edx
  3. unsigned char code[]=
  4. {
  5. 0xBA,0x0C,0xE6,0x03,0x00,
  6. 0xB9,0x0C,0xE6,0x03,0x00,
  7. 0xBB,0x0C,0xE6,0x03,0x00,
  8. 0xB8,0x0C,0xE6,0x03,0x00,
  9. 0xC3
  10. };
  11. //execute le code
  12. void exec()
  13. {
  14.     void *exec = (void *)code;
  15.     _asm
  16.     {
  17.         call exec;
  18.     }
  19. }
  20. int main()
  21. {
  22.     //bourre un max de var dans les reg
  23.     DWORD t = GetTickCount();
  24.     DWORD u = GetTickCount();
  25.     DWORD s = GetTickCount();
  26.     DWORD v = GetTickCount();
  27.     exec();
  28.     t =GetTickCount() - t;
  29.     u =GetTickCount() - u;
  30.     s =GetTickCount() - s;
  31.     v =GetTickCount() - v;
  32.     //affiche le chef d'oeuvre. NOrmalement on devrait avoir des chiffres compris entre 0 et 10
  33.     //sauf si le compilo se fait berner par notre pauvre code
  34.     printf("%d,%d,%d,%d\n",t,u,s,v);
  35.     return 0;
  36. }


(a compiler avec options d'optim au max)
 
ce que je trouve rigolo, dans l'affaire, c'est que visu laisse des var dans les reg malgré des appels a d'autre fonction. Perso j'aurais pensé qu'il sauvait tout en RAM (étant donné qu'on ne sait pas trop ce qu'une fontion donnée peut bien faire avec les regs....), mais bon, pas l'air d'etre le cas :D

Reply

Marsh Posté le 01-11-2002 à 13:30:23   

Reply

Marsh Posté le 01-11-2002 à 14:25:22    

Utilise plutot QueryPerformanceCounter et QueryPerformanceFrequency (un truc dans ce genre) pour mesurer. Ou le profiler ce VC++

Reply

Marsh Posté le 01-11-2002 à 15:04:20    

fabsk a écrit a écrit :

Utilise plutot QueryPerformanceCounter et QueryPerformanceFrequency (un truc dans ce genre) pour mesurer. Ou le profiler ce VC++




 
oué, of, ct pour avoir une idée des proportions, pas pour avoir le tps exact..... pour le coup ca a fait son boulot

Reply

Marsh Posté le 02-11-2002 à 20:38:24    

Ben moi ca me semble normal...tout ce que tu appelle sont des procedures internes à ton prg...Tu voudrais pas que Win sauve le contexte à chaque tu fais un appel à une de tes procédures?
C'est à toi de vérifier que tu fais pas n'importe quoi avec tes registres, non?


---------------
Horizon pas Net, reste à la buvette!!
Reply

Marsh Posté le 02-11-2002 à 20:46:51    

Willyzekid a écrit a écrit :

Ben moi ca me semble normal...tout ce que tu appelle sont des procedures internes à ton prg...Tu voudrais pas que Win sauve le contexte à chaque tu fais un appel à une de tes procédures?
C'est à toi de vérifier que tu fais pas n'importe quoi avec tes registres, non?




 
bah nan. Enfin, si. Je veux dire, en tant que programmeur C++ je veux pas savoir ce que fait le compilo. Si jamais je me met a ecraser du reg a coup d'asm inline parce que ca me chante, ben j'ai pas envie que suite a ca tout mon prog parte en eau de boudin.  (bon la c un tres special vu qu'au moment de la compil il peut pas savoir ce qu'il se passe).
 
Non, en fait ce qui m'a supris c'est le fait qu'il arrive a gerer ses regs malgré des appels proceduraux (bon, visiblement, j'ai regardé, dans la litterature c'est du "interprocedural register allocation", donc ca rien de trop trop surprenant)
 
 
'fin bref, j'etais plutot soulagé de  
1) avoir découvert ce bug potentiel qui pouvait faire foirer le prog dans lequel va tourner le compilo
2) voir que c t pas mon compilo qui petait un cable
3) avoir appris qqchose  
 
par soulagement g donc creer ce topic :D

Reply

Marsh Posté le 02-11-2002 à 21:35:32    

chrisbk a écrit a écrit :

 
 
bah nan. Enfin, si. Je veux dire, en tant que programmeur C++ je veux pas savoir ce que fait le compilo. Si jamais je me met a ecraser du reg a coup d'asm inline parce que ca me chante, ben j'ai pas envie que suite a ca tout mon prog parte en eau de boudin.  (bon la c un tres special vu qu'au moment de la compil il peut pas savoir ce qu'il se passe).
 




 
Ben oui...c'est un peu de ta faute quand même :D
Donc ton topic, là, c'est pas pour te rassurer, en fait, c'est pour nous montrer à quel point tu t'es planté :D
 
A passage, ton compilo, tu le fais en combien de passe? avec quelle struct.? etc.


Message édité par Willyzekid le 02-11-2002 à 21:36:47

---------------
Horizon pas Net, reste à la buvette!!
Reply

Marsh Posté le 02-11-2002 à 22:00:58    

Willyzekid a écrit a écrit :

 
 
Ben oui...c'est un peu de ta faute quand même :D
Donc ton topic, là, c'est pas pour te rassurer, en fait, c'est pour nous montrer à quel point tu t'es planté :D
 
A passage, ton compilo, tu le fais en combien de passe? avec quelle struct.? etc.




 
bah nan, je me suis pas specialement planté, c juste que j'avais pas du tout pensé a ca comme pb :D
maintenant je me demande si il n'y a pas que ebx de concerné. EAX est de toute facon utilisé pour le retour, ECX par le this, reste EDX (parfois utilisé pour le code de retour). aucune idée de ce que fait VC avec EDI/ESI, si il leur reserve qqchose de particulier....
 
le compilo, ben le parse de fichier c avec flex/bison, le reste c tout des trucs a moi. tu veux savoir quoi exactement ?
 
 
 

Reply

Marsh Posté le 04-11-2002 à 14:48:24    

chrisbk a écrit a écrit :

 
 
bah nan, je me suis pas specialement planté, c juste que j'avais pas du tout pensé a ca comme pb :D
maintenant je me demande si il n'y a pas que ebx de concerné. EAX est de toute facon utilisé pour le retour, ECX par le this, reste EDX (parfois utilisé pour le code de retour). aucune idée de ce que fait VC avec EDI/ESI, si il leur reserve qqchose de particulier....




 
Ca c'est les joies de coller de l'ASM dans du C...Tu as intérêt à vérifier quelles registres utilise ton prg..
 
 
 

chrisbk a écrit a écrit :

 
le compilo, ben le parse de fichier c avec flex/bison, le reste c tout des trucs a moi. tu veux savoir quoi exactement ?



 
Merde, c'est le parser qui m'intéressait...
Et tu le fait tourner comment par rapport au générateur de code? Ils sont l'un à la suite de l'autre? en parallèle (producteur/consomateur?)


---------------
Horizon pas Net, reste à la buvette!!
Reply

Marsh Posté le 04-11-2002 à 16:06:05    

Willyzekid a écrit a écrit :

 
 
Ca c'est les joies de coller de l'ASM dans du C...Tu as intérêt à vérifier quelles registres utilise ton prg..




 
no fear, je sauve maintenant tous les regs avant et je remet apres :D
 
 
 

Willyzekid a écrit a écrit :

 
Merde, c'est le parser qui m'intéressait...
Et tu le fait tourner comment par rapport au générateur de code? Ils sont l'un à la suite de l'autre? en parallèle (producteur/consomateur?)




 
ah ben ecoute, si y'a des outils qui font le boulot pour toi.... :D
 
En fait le parser me genere un arbre de syntaxe abstraite. A partir de cet arbre je compile en un langage intermediaire (genre a = b + c + d va etre compilé en tmp = c + d; a = tmp + b;)
 
Et ensuite ce code va etre compilé en langage cible (genre l'ASM la) (normalement entre els deux tu es censé mettre les optims mais la c temporairement désactiver)

Reply

Marsh Posté le 06-11-2002 à 04:32:50    

MSDN, rubrique "Optimizing Inline Assembly" a écrit :

 
the presence of an __asm block affects register variable storage. The compiler avoids enregistering variables across an __asm block if the register?s contents would be changed by the __asm block.



Ce qui veut donc dire que dans le doute, il prend l'option risquée...
Erreur de leur part, c'est évident.


Message édité par Musaran le 06-11-2002 à 04:35:31

---------------
Bricocheap: Montage de ventilo sur paté de mastic silicone
Reply

Marsh Posté le 06-11-2002 à 04:32:50   

Reply

Marsh Posté le 06-11-2002 à 09:32:55    

Musaran a écrit a écrit :

 
Ce qui veut donc dire que dans le doute, il prend l'option risquée...
Erreur de leur part, c'est évident.




 
j'ai plutot l'impression qu'il prend l'option "safe" ("The compiler avoids enregistering variables across an __asm block". Si je cprends bien tout, il evite de laisser des variables dans les reg si ledit reg est modif par le block asm)

Reply

Marsh Posté le 07-11-2002 à 04:58:44    

Dans ce cas-ci, voyant un call sur du code inconnu, il suppose qu'il n'y a pas de changements... Suicidaire !
 
Test VC++ 6 sp 5:

149853665,0,0,0


---------------
Bricocheap: Montage de ventilo sur paté de mastic silicone
Reply

Marsh Posté le 07-11-2002 à 12:52:01    

C'est un fait....spour ca que ca serait interessant de voir comment se débrouillent les autre compilos vis a vis de ce cas la

Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed