CONNEXION
  • RetourJeux
    • Sorties
    • Hit Parade
    • Les + populaires
    • Les + attendus
    • Soluces
    • Tous les Jeux
    • Gaming
  • RetourActu Gaming
    • News
    • Astuces
    • Tests
    • Previews
    • Toute l'actu gaming
  • RetourBons plans
    • Bons plans
    • Bons plans Smartphone
    • Bons plans Hardware
    • Bons plans Image et Son
    • Bons plans Amazon
    • Bons plans Cdiscount
    • Bons plans Decathlon
    • Bons plans Fnac
    • Tous les Bons plans
  • RetourJVTech
    • Actus High-Tech
    • Intelligence Artificielle
    • Smartphones
    • Mobilité urbaine
    • Hardware
    • Image et son
    • Tutoriels
    • Tests produits High-Tech
    • Guides d'achat High-Tech
    • JVTech
  • RetourCulture
    • Actus Culture
    • Culture
  • RetourVidéos
    • A la une
    • Gaming Live
    • Vidéos Tests
    • Vidéos Previews
    • Gameplay
    • Trailers
    • Chroniques
    • Replay Web TV
    • Toutes les vidéos
  • RetourForums
    • Hardware PC
    • PS5
    • Switch 2
    • Xbox Series
    • Switch
    • Pokemon pocket
    • FC 25 Ultimate Team
    • League of Legends
    • Tous les Forums
  • PC
  • PS5
  • Xbox Series
  • Switch 2
  • PS4
  • One
  • Switch
  • iOS
  • Android
  • MMO
  • RPG
  • FPS
En ce moment Genshin Impact Valhalla Breath of the wild Animal Crossing GTA 5 Red dead 2
Liste des sujets

Alors là, je comprend pas... (C++)

Blawk
Blawk
Niveau 10
03 septembre 2003 à 17:14:10

Salut,

J´ai écrit une fonction C++ qui fait une opération sur un unsigned char ( byte).
La voici:

__forceinline
byte multi2(byte num)
{
byte tmp = num < < 1;
if ( num & 128) tmp ^= 0x1b;
return tmp;
}

Pensant l´optimiser, le l´ai réécrite en ASM:

__forceinline
byte multi2(byte num) {

__asm {
// tmp = num < < 1
mov AL, num
mov AH, AL
shl AL, 1

// if ( num & 128)
cmp AH, 0
jns NOMOD
// tmp ^= 0x1b
xor AL, 1bh

NOMOD:
};
}

Et bien devinez quoi, la première est plus rapide, alors que en mode debug, l´ASM de la première est bien plus compliqué que celui de la première ( plus d´instruction, utilisation de 2 registre 32bits...)...

hs_dino
hs_dino
Niveau 9
03 septembre 2003 à 18:42:48

En gros tu essayes de comprendre pourquoi les ingenieurs qui ont fait ton compilateur sont meilleur que toi?

Bah... la réponse est peut etre dans la question :)

DarkPaladin
DarkPaladin
Niveau 5
03 septembre 2003 à 19:19:01

Blawk: Il dirait plus une fonction pour faire la rotation d´un 8Bits. A l´exception que tu as rajouté un ´b´ 0x1b(27)11011 dans le " Xor".
Si c´est pour faire une rotation de bits, les valeurs sont erronées apres 127..255.

JL´ai Optimisé.

byte Multi2(byte num)
{
__asm
{
Mov Al,num
Rol Al,1
}
}

Blawk
Blawk
Niveau 10
04 septembre 2003 à 11:09:18

En fait, je pense avoir compris. La première fonction étant ecrite en C++ le compilateur la comprend mieux et optimise ainsi la façon dont est elle utilisé, mais le contenu de le première est effectivement plus long à exécuter que celui de la deuxième.

DarkPaladin > Si c´était juste un rotation, je m´en serais rendu compte.
La fonction fait ceci:
initialise tmp sur 2*num.
Si num > = 128, tmp ^= 0x1b.

DarkPaladin
DarkPaladin
Niveau 5
04 septembre 2003 à 15:46:03

Equivalent.

unsigned char Multi2(unsigned char num)
{
__asm
{
Mov Al,num
Shl Al,1
Jnc N
Xor Al,0x1B
N:
}
}

Blawk
Blawk
Niveau 10
04 septembre 2003 à 19:02:56

Pas mal :-)

Blawk
Blawk
Niveau 10
04 septembre 2003 à 19:08:38

Mais toujours un peu plus lent que la version C++...

arnaud81
arnaud81
Niveau 7
05 septembre 2003 à 01:42:32

black, le code de paladin est parfait, on ne peut faire on ne peu plus court.

Si le code est plus long a executer je vois plusiseurs possibilité :

  • les registres sont sauvegardés & restaurés quand on passe & sort de la fonctions en assembleurs ( sauf al evident)
  • la pile est sauvegardée, restaurée, vérifiée ( car tu dois compiler en mode debug je suppose et comme l´humain est plus sujet a faire des erreurs, je suppose que le compilo vérifie ca 2fois plus ! )

==> pour vérifier que c´est ca ( c tout simple lol) il suffit de mettre dans les accolades, le code assembleur généré par ton compilateur et de vérifier quel code est le plus rapide !

i_am_the_law
i_am_the_law
Niveau 6
05 septembre 2003 à 02:21:56

je sais pas comment tu verifie ca mais qd on regarde le code asm genere, la fonction asm contient bcp moins d instructions que la fonction " normale" a noter que le forceinline n´a pas marche vu qu´il y a un call, comme quoi :)
La fonction asm possede 4 inscrutions en + 2 push et 2 pop pour esi et edi, pour + de surete surement.

voici le listing ( j´ai peur de voir le resultat avec ce forum)

je marque juste le code de la fonction, pas le reste.

? Multi2@@YAEE@Z PROC NEAR ; Multi2, COMDAT
; 14 : {
push ebp
mov ebp, esp
push ebx
push esi
push edi
; 15 :
; 16 : __asm
; 17 : {
; 18 : Mov Al,num
mov al, BYTE PTR _num$[ebp]
; 19 : Shl Al,1
shl al, 1
; 20 : Jnc N
jae SHORT $N$217
; 21 : Xor Al,0x1B
xor al, 27 ; 0000001bH
$N$217:
; 22 : N:
; 23 : }
; 24 :
; 25 : }
pop edi
pop esi
pop ebx
pop ebp
ret 0
? Multi2@@YAEE@Z ENDP ; Multi2

et voici la fonction " normale"
? Multi2@@YAEE@Z PROC NEAR ; Multi2, COMDAT

; 29 : {

push ebp
mov ebp, esp
push ecx

; 30 : unsigned char tmp=num<<=1;

mov al, BYTE PTR _num$[ebp]
shl al, 1
mov BYTE PTR _num$[ebp], al
mov cl, BYTE PTR _num$[ebp]
mov BYTE PTR _tmp$[ebp], cl

; 31 : if ( num &128 ) num ^= 0x1b;

mov edx, DWORD PTR _num$[ebp]
and edx, 255 ; 000000ffH
and edx, 128 ; 00000080H
test edx, edx
je SHORT $L218
mov al, BYTE PTR _num$[ebp]
xor al, 27 ; 0000001bH
mov BYTE PTR _num$[ebp], al
$L218:

; 32 : return num;

mov al, BYTE PTR _num$[ebp]

; 33 : }

mov esp, ebp
pop ebp
ret 0
? Multi2@@YAEE@Z ENDP ; Multi2

j´ai du mal a voir comment tu peux dire que la fonction asm est + lente et j´ai la flemme de mesurer ( si qqn veut bien se devouer) :)

i_am_the_law
i_am_the_law
Niveau 6
05 septembre 2003 à 02:25:17

erf tjrs se relire avant de poster... je m´etais trompe dans la fonction normale :
j´avais mis un = en trop, dans cette version le code a moins d instruction mais il n´en garde pas moins 1 + gd nb que la version asm

; 30 : unsigned char tmp=num<<1;

mov eax, DWORD PTR _num$[ebp]
and eax, 255 ; 000000ffH
shl eax, 1
mov BYTE PTR _tmp$[ebp], al

i_am_the_law
i_am_the_law
Niveau 6
05 septembre 2003 à 02:45:27

bon ca me paraissait bizarre qu´il y ait tant d instructions et j´avais fait une autre erreur dc voici la fonction normale :)

; 29 : {

push ebp
mov ebp, esp
push ecx

; 30 : unsigned char tmp=num<<1;

mov eax, DWORD PTR _num$[ebp]
and eax, 255 ; 000000ffH
shl eax, 1
mov BYTE PTR _tmp$[ebp], al

; 31 : if ( num & 128 ) tmp ^= 0x1b;

mov ecx, DWORD PTR _num$[ebp]
and ecx, 255 ; 000000ffH
and ecx, 128 ; 00000080H
test ecx, ecx
je SHORT $L218
mov dl, BYTE PTR _tmp$[ebp]
xor dl, 27 ; 0000001bH
mov BYTE PTR _tmp$[ebp], dl
$L218:

; 32 : return tmp;

mov al, BYTE PTR _num$[ebp]

; 33 : }

c´est la fatigue ; )

il est a noter que le fait d´utiliser des char, fait qu´on doit faire 2 and en + vu que le compilateur travaille sur des registres 32 bits et qu´a chaque fois il reutilise la variable tmp ou num en memoire

Blawk
Blawk
Niveau 10
05 septembre 2003 à 12:21:55

J´ai mesuré avec un clock()-clock()

Peut-être que la fonction C++ est INLINE en mode release, mais pas l´ASM...

arnaud81
arnaud81
Niveau 7
05 septembre 2003 à 22:03:12

bah il est clair que programmé " a la main", la fonction est plus rapide, ensuite, pour le reste ca dépend plus de nous :)

Sous forums
  • Aide à l'achat Mac
  • Création de sites web
  • Création de Jeux
  • Linux
  • Programmation
  • Internet
  • Steam Deck
  • Macintosh
  • Hardware
La vidéo du moment