SWAP DE DEUX VARIABLES EN C++ / ASM

vinc1008881 Messages postés 257 Date d'inscription dimanche 22 août 2004 Statut Membre Dernière intervention 29 septembre 2010 - 24 juil. 2006 à 19:58
BruNews Messages postés 21040 Date d'inscription jeudi 23 janvier 2003 Statut Modérateur Dernière intervention 21 août 2019 - 5 août 2006 à 00:02
Cette discussion concerne un article du site. Pour la consulter dans son contexte d'origine, cliquez sur le lien ci-dessous.

https://codes-sources.commentcamarche.net/source/38766-swap-de-deux-variables-en-c-asm

BruNews Messages postés 21040 Date d'inscription jeudi 23 janvier 2003 Statut Modérateur Dernière intervention 21 août 2019
5 août 2006 à 00:02
Il y a 2 pipelines sur Pentium.
; eax échange ecx
mov edx, eax
mov eax, ecx ; 1er cycle fini, pas de pénalité car EAX
nop ; surement autre chose à faire dans le prog, mais bon...
mov ecx, edx

Michael Abrash a écrit des chapitres passionnants sur le sujet, s'y reporter.
zeratul67 Messages postés 97 Date d'inscription mardi 9 avril 2002 Statut Membre Dernière intervention 11 mai 2008
4 août 2006 à 16:39
C'est vrai que pour les débutants, cela peut induire en erreur. Malgré tout, les commentaires peuvent être intéressants, avec entre autre l'URL donnée par vecchio56 et les information sur la façon d'écrire de l'ASM dans du code C (les deux syntaxe différentes).
Finalement, histoire ce clore au cas où tout cela serait supprimé, qu'est-ce qui est le plus rapide, sans utiliser l'ASM ? Les mov avec variable temporaire, les xor ?

J'ai également un peu de mal à te comprendre BruNews, la série de mov qui permet l'échange est parallelizable ?!
BruNews Messages postés 21040 Date d'inscription jeudi 23 janvier 2003 Statut Modérateur Dernière intervention 21 août 2019
4 août 2006 à 16:03
Ce genre de "source" est à oublier, ne peut qu'induire un débutant en erreur.
L'optimisation asm ne vaut que si la fonction est complet en asm, autrement c'est tout le contraire qui est obtenu. Il est impossible de savoir si le compilo a créé des variables sur pile ou si les valeurs sont tenues en registre, en ce cas des PUSH POP sont une totale aberration quand 3 MOV suffisaient.
XCHG est obsolète depuis le 486 et à bannir depuis le pentium avec lequel les MOV sont parallélisables.

Cette ineptie disparaitra samedi soir au plus tard.
vecchio56 Messages postés 6535 Date d'inscription lundi 16 décembre 2002 Statut Membre Dernière intervention 22 août 2010 14
28 juil. 2006 à 05:04
En général quand on code en C, on se moque des flags du CPU
Mais dans ton exemple ya pas d'overflow a mon avis, car 0xFFFFFFFE représente -2 (donc a+b=0 et non 1)
vinc1008881 Messages postés 257 Date d'inscription dimanche 22 août 2004 Statut Membre Dernière intervention 29 septembre 2010 3
27 juil. 2006 à 22:36
j'en sais rien, peut-etre que sa marche avec toute les valeurs, mais ce que je peux dire c'est que le flag of du registre flags du CPU sera peut-etre à 1 à cause de cet overflow.
cs_aardman Messages postés 1905 Date d'inscription mercredi 22 janvier 2003 Statut Membre Dernière intervention 17 septembre 2012 3
27 juil. 2006 à 20:14
y'a un overflow... mais ca marche ? c'est un peu contradictoire.
Pour quel couple de valeur (par exemple) cette technique ne fonctionne pas ?
vinc1008881 Messages postés 257 Date d'inscription dimanche 22 août 2004 Statut Membre Dernière intervention 29 septembre 2010 3
27 juil. 2006 à 19:30
ouais ça marche mais c'est pas tres propre l'overflow...mieux vieux utiliser un xor, en plus c'est plus rapide.
vecchio56 Messages postés 6535 Date d'inscription lundi 16 décembre 2002 Statut Membre Dernière intervention 22 août 2010 14
27 juil. 2006 à 19:16
int a = 0xFFFFFFFE;
int b = 0x2;

a = a + b;
b = a - b;
a = a - b;

Ca marche très bien chez moi
vinc1008881 Messages postés 257 Date d'inscription dimanche 22 août 2004 Statut Membre Dernière intervention 29 septembre 2010 3
27 juil. 2006 à 19:03
t'as risque de overflow avec cette méthode.

int a = 0xFFFFFFFE
int b = 0x2

a+b = 1 ;-)

apres travailler avec des nombre codé sur 8 octet c'est trop lent
cs_aardman Messages postés 1905 Date d'inscription mercredi 22 janvier 2003 Statut Membre Dernière intervention 17 septembre 2012 3
27 juil. 2006 à 18:17
Salut,
Dans le meme genre que xor, mais avec des additions/soustractions:
a = a + b;
b = a - b;
a = a - b;
cs_neria Messages postés 319 Date d'inscription vendredi 21 février 2003 Statut Membre Dernière intervention 16 février 2009
26 juil. 2006 à 09:54
Je précise que la syntaxe dans #ifdef __GNUC__ est en fait la syntaxe AT&T qui est celle par défaut sous gcc (mais rien ne vaut la syntaxe intel :p).
nicolas66 Messages postés 116 Date d'inscription mercredi 25 décembre 2002 Statut Membre Dernière intervention 4 janvier 2009
25 juil. 2006 à 22:46
Arf c'est déjà pas si mal :p.
vecchio56 Messages postés 6535 Date d'inscription lundi 16 décembre 2002 Statut Membre Dernière intervention 22 août 2010 14
25 juil. 2006 à 19:01
Portable c'est toi qui le dit. Il me semble que ton code ne compilera que sur une architecture x86
nicolas66 Messages postés 116 Date d'inscription mercredi 25 décembre 2002 Statut Membre Dernière intervention 4 janvier 2009
25 juil. 2006 à 18:37
Je ne pensais pas que ce simple morceau de code lancerait une polémique aussi grande. Je tiens simplement à dire que ce programme n'était là que pour montrer qu'on peut écrire de l'assembleur en ligne avec du code C++ et de rendre portable le tout. Je n'ai pas vocation à être un as de l'assembleur.
cs_eRoZion Messages postés 241 Date d'inscription vendredi 23 mai 2003 Statut Membre Dernière intervention 8 octobre 2007 1
25 juil. 2006 à 16:23
Merci vecchio pour le lien wiki.
C'est incroyablement logique mais fallait y penser!
cs_thebigbang Messages postés 196 Date d'inscription vendredi 21 décembre 2001 Statut Membre Dernière intervention 25 juillet 2006
25 juil. 2006 à 13:57
vecchio56, tu auras été plus rapide que moi :)
cs_thebigbang Messages postés 196 Date d'inscription vendredi 21 décembre 2001 Statut Membre Dernière intervention 25 juillet 2006
25 juil. 2006 à 13:56
si tu veux faire de l'assembleur, xchg me paraît la meilleure solution pour échanger deux variables, plutôt que d'utiliser la pile.
Pour ce qui est des xor, tu peux faire ça pour échanger a et b :

a <- xor(a,b)
b <- xor(a,b)
a <- xor(a,b)

Pour échanger eax et ecx :
xor eax, ecx
xor ecx, eax
xor eax, ecx

Peut être que xchg fonctionne comme ça ?
vecchio56 Messages postés 6535 Date d'inscription lundi 16 décembre 2002 Statut Membre Dernière intervention 22 août 2010 14
25 juil. 2006 à 13:55
zeratul67 Messages postés 97 Date d'inscription mardi 9 avril 2002 Statut Membre Dernière intervention 11 mai 2008
25 juil. 2006 à 11:33
ces petites codes sont intéressants pour les débats qu'ils provoquent, mais pas directement pour leur contenu.
Concernant "A(12)", je pensequ'il vaut mieux écrire "A = 12", c'est plus lisible, c'est compatible C ... vous voyez des avantages à A(12) ?

Pour sawper deux variables, il me semble qu'il y a une technique à base d'oppérateurs logiques (des xor peut être) qui le permet sans création de variable tampon. (je ne dit pas qu'elle a de l'intérêt ... :P)
vinc1008881 Messages postés 257 Date d'inscription dimanche 22 août 2004 Statut Membre Dernière intervention 29 septembre 2010 3
25 juil. 2006 à 10:49
il me semble que ces 2 lignes veulent dire charge A dans eax et charge b dans ebx >> "a"(A), "b"(B) et charge b à partir de ebx et charge a à partir de eax >> "=a"(A), "=b"(B), ce ne suis pas sur car je comprends pas grand chose à la syntaxe at&t...

en fait pour faire le swap de 2 variable il faut pour son code 4 mov et 4 push/pop, c'est de la désoptimisation :-)
vecchio56 Messages postés 6535 Date d'inscription lundi 16 décembre 2002 Statut Membre Dernière intervention 22 août 2010 14
25 juil. 2006 à 05:06
Economiser 4 octets, c'est pas vraiment le genre d'optimisation qu'on recherche en général (en l'occurence ton code est plus lent qu'un code érit en C, comme le dit vinc1008881)
Mais c'est la première partie en assembleur qui m'interpelle, surtout la fin:
# : "=a"(A), "=b"(B) // Output
# : "a"(A), "b"(B) // Input
C'est bizarre ces lignes-là, ca veut dire quoi exactement?

Pour le int A(12) c'est effectivement possible en C++, car C++ considère les types de bases comme des classes (et donc a est un objet). Cependant pas de notation pointée pour les types de base
luhtor Messages postés 2023 Date d'inscription mardi 24 septembre 2002 Statut Membre Dernière intervention 28 juillet 2008 6
24 juil. 2006 à 23:29
gcc non, mais g++ oui. C'est juste un appel au constructeur, la méthode la plus classique.
vinc1008881 Messages postés 257 Date d'inscription dimanche 22 août 2004 Statut Membre Dernière intervention 29 septembre 2010 3
24 juil. 2006 à 21:52
franchement, je sais pas si j'ai loupé une page de "C for beginers" mais de comprends pas là, int A(12); ça veux dire quoi ? (gcc ne le compile pas en tout cas)
luhtor Messages postés 2023 Date d'inscription mardi 24 septembre 2002 Statut Membre Dernière intervention 28 juillet 2008 6
24 juil. 2006 à 21:17
"int A(12)" n'a rien de choquant.
vinc1008881 Messages postés 257 Date d'inscription dimanche 22 août 2004 Statut Membre Dernière intervention 29 septembre 2010 3
24 juil. 2006 à 21:01
je confirme : grace à http://home.comcast.net/~fbui/intel.html , sur un i486 il te faut 20 cycle de cpu avec ton code et 7 pour le mien.
vinc1008881 Messages postés 257 Date d'inscription dimanche 22 août 2004 Statut Membre Dernière intervention 29 septembre 2010 3
24 juil. 2006 à 19:58
salut, j'ai remarqué quelques trucs :

- c'est quoi ce int A(12) ??? tu voulais dire int A = 12 ?
- en géneral pour des noms de variables on met des minuscules
- tu devrais mettre asm volatile (/*instruction*/); car rien ne te dis que le compilo va respecter strictement l'ordre et meme les instruction l'interieur de asm ();
- pas simpa de modifier ebx, des plantages peuvent se produire (pour eax, je crois que il n'y a pas de danger)
- question temps, c'est pas fameux : push et pop emploient plus de cycles cpu que des mov en plus il temps faut 4 push/pop au lieu de 3 mov
- dernière remarque, l'instruction assembleur xchg existe...

CODE :
asm volatile (
mov eax, a
xchg eax, b;
mov a, eax);

ok, j'arrete là mon réquisitoire....