RSS Feed

Probleme asm pe “release”

January 19th, 2008

Problema de fata apare in versiunele 2005+ ale Visual Studio in modul de compilare "Release". Sa luam exemplul urmator:

C++:
  1. int functie(int)
  2. {
  3.    _asm
  4.          {
  5.            mov eax,[ebp+8]
  6.           }
  7. }
  8.  
  9.  
  10. int main()
  11. {
  12. int a=10,b;
  13. b=functie(a);
  14. printf("%d ",b);
  15. return 0;
  16. }

In mod normal, functia returneaza valoarea primita ca parametru . Prin urmare, b=functie(a) va lua valoarea lui a, adica 10. Pana acum toate bune si frumoase. Sa compilam acum pe "Release mode" . De data aceasta, b va lua valoarea ...0 :) . Ciudat ? Nicidecum. Daca vom modifica antetul functiei main in felul urmator:

C++:
  1. int main(int)

b va lua valoarea ... 1 :) ... acum sa rulam programul cu 5 parametri ... si da, intr-adevar , b va lua valoarea 5 ... hmmm...Situatia nu e atat de hazlie pe cat pare. Sa zicem ca avem o functie care primeste ca parametru adresa unei variabile ... daca in loc de adresa noi primim 0, 1 sau alte tampenii, cu siguranta ca programul nostru va functiona razna iar noi ne vom pune nervii la incercare pentru mult timp, cu debugger-ul etc., negasind eroarea.

Eroarea provine din cauza optimizarilor de cod pe care le efectueaza Visual Studio . Sa luam acelasi caz de mai sus. Ce inseamna optimizare ? Compilatorul "vede" ca functia de mai sus nu mai apeleaza alte functii si este apelata doar din main . Asa ca , literal, ia tot codul functiei si il pune in locul apelului din functia main . Ceea ce echivaleaza perfect cu :

C++:
  1. int main()
  2. {
  3. int a=10,b;
  4.    _asm
  5.          {
  6.            mov eax,[ebp+8]
  7.            mov b,eax
  8.           }
  9. printf("%d ",b);
  10. return 0;
  11. }

Astfel, nu se mai face saltul la codul functiei, codul e "performant", dar intelesul sau deja se schimba...
In mod logic, problema se rezolva in 2 moduri :

1. Spunem compilatorului sa nu mai optimizeze nimic ( foarte usor : Project Properties -> Configuration Properties -> C/C++ -> Optimization -> Optimization -> Disabled .
2. Spunem compilatorului sa nu optimizeze functia noastra ... va urma

Visual Studio 2008 … interesant

January 9th, 2008

Hmm .. eram obisnuit sa setez release, si dau f5 , sa astept sa termina de incarcat aberatiile respective si sa am executabilul ... vremuri bune . Pe Visual Studio mai vechi poti face acest lucru pentru un program de tip console application. Se pare ca, mai nou, acest lucru nu mai este disponibil direct in Visual Studio 2008 . Daca dati simplu release si dati altcuiva programul, sunt sanse mari ca acesta sa nu-i mearga ( logica spune asa : daca eu sunt singurul tampit care foloseste Visual Studio 2008 cu .net 3.5, iar ceilalti folosesc altceva, e clar ca nu va merge ) . Problema se rezolva foarte simplu. Mergeti la Properties->Configurations Properties-> C/C++ ->Code Generation->Runtime Library-> Multi-threaded (/MT)... atata tot ... acum dati prietenilor programul vostru si virusati-i :d

Naiv Sort - C++/ASM

January 1st, 2008

Ah ... 2008 ... un nou an ... Dupa sampanie si cozonac ( meniu special de revelion ) , dupa artificii ( pe faleza Dunarii ) ...
Ma bucur cel putin ca acum folosesc un soft de anu asta ( Visual Studio 2008 ) , sunt trist ca in curand vin examenele, sunt bucuros ca in scurta vacanta de Craciun am reusit sa invat ASM ( un limbaj imposibil pentru mine la inceput - cu ocazia asta, tin sa-i multumesc lui AndreiASM .. de la el am invatat o buna parte a limbajului dar si profului ... printre cei mai de treaba de la FII ) ...
Si ca sa incep anul cu dreptul, m-am gandit in seara asta sa schimb algoritmul de anul trecut ( bubble sort ) , cu unul de "anul asta" ( naiv sort ) ... am implementat atat in C++ cat si in ASM ...

C++:
  1. #include <stdio.h>
  2.  
  3. int v[5];
  4. /*
  5. void interschimba(int &a,int &b)
  6. {
  7.     int c;
  8.     c=a;
  9.     a=b;
  10.     b=c;
  11. }
  12. void Naiv_Sort(int v[],int n)
  13. {
  14.     int i,poz,min,j;
  15.     for(i=0;i<n;i++)
  16.     {
  17.         min=v[i];
  18.         poz=i;
  19.        
  20.         for(j=i+1;j<n;j++)
  21.             if(v[j]<min)
  22.             {
  23.                 min=v[j];
  24.                 poz=j;
  25.             }
  26.         interschimba(v[i],v[poz]);
  27.     }
  28. }*/
  29.  
  30. void Naiv_Sort(int*,int)
  31. {
  32.     _asm
  33.     {
  34.         mov ebx,0
  35. for_mare:
  36.         mov ecx,[ebp+12]
  37.         dec ecx
  38.         cmp ebx,ecx
  39.         je gata
  40.         mov esi,[ebp+8]
  41.         //ajungem pe pozitia curenta
  42.         mov eax,ebx
  43.         shl eax,2
  44.         add esi,eax
  45.         //in esi avem pozitia curenta
  46.         //in eax avem minimul, in edx avem pozitia minimului
  47.         mov eax,[esi]
  48.         mov edx,ebx
  49.         //ecx va fi contorul celui de-al doilea for
  50.         mov ecx,ebx
  51.         inc ecx
  52.         add esi,4
  53. for_mic:
  54.         cmp ecx,[ebp+12]
  55.         je stop
  56.         mov edi,[esi]
  57.         cmp edi,eax
  58.         jb schimba
  59.         jmp continua
  60. schimba:
  61.         mov eax,[esi]
  62.         mov edx,ecx
  63.         jmp continua
  64. continua:
  65.         add esi,4
  66.         inc ecx
  67.         jmp for_mic
  68. stop:
  69.         mov esi,[ebp+8]
  70.         mov eax,ebx
  71.         shl eax,2
  72.         add esi,eax
  73.         mov edi,[ebp+8]
  74.         mov eax,edx
  75.         shl eax,2
  76.         add edi,eax
  77.         //in esi si edi am cele 2 adrese ale elementelor ce trebuie schimbate
  78.        
  79.         push dword ptr [esi]
  80.         push dword ptr [edi]
  81.         pop dword ptr [esi]
  82.         pop dword ptr [edi]
  83.  
  84.         inc ebx
  85.         jmp for_mare
  86. gata:
  87.  
  88.     }
  89. }
  90.  
  91.  
  92. int main()
  93. {
  94.     int n,i;
  95.     n=5;
  96.     v[0]=10;v[1]=2;v[2]=1;v[3]=5;v[4]=6;
  97.     Naiv_Sort(v,n);
  98.     for(i=0;i<n;i++) printf("%d ",v[i]);
  99.     getchar();
  100.     return 0;
  101. }