Probleme asm pe “release”
Problema de fata apare in versiunele 2005+ ale Visual Studio in modul de compilare "Release". Sa luam exemplul urmator:
-
int functie(int)
-
{
-
_asm
-
{
-
mov eax,[ebp+8]
-
}
-
}
-
-
-
int main()
-
{
-
int a=10,b;
-
b=functie(a);
-
printf("%d ",b);
-
return 0;
-
}
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:
-
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 :
-
int main()
-
{
-
int a=10,b;
-
_asm
-
{
-
mov eax,[ebp+8]
-
mov b,eax
-
}
-
printf("%d ",b);
-
return 0;
-
}
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
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![]()
Naiv Sort - C++/ASM
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 ...
-
#include <stdio.h>
-
-
int v[5];
-
/*
-
void interschimba(int &a,int &b)
-
{
-
int c;
-
c=a;
-
a=b;
-
b=c;
-
}
-
void Naiv_Sort(int v[],int n)
-
{
-
int i,poz,min,j;
-
for(i=0;i<n;i++)
-
{
-
min=v[i];
-
poz=i;
-
-
for(j=i+1;j<n;j++)
-
if(v[j]<min)
-
{
-
min=v[j];
-
poz=j;
-
}
-
interschimba(v[i],v[poz]);
-
}
-
}*/
-
-
void Naiv_Sort(int*,int)
-
{
-
_asm
-
{
-
mov ebx,0
-
for_mare:
-
mov ecx,[ebp+12]
-
dec ecx
-
cmp ebx,ecx
-
je gata
-
mov esi,[ebp+8]
-
//ajungem pe pozitia curenta
-
mov eax,ebx
-
shl eax,2
-
add esi,eax
-
//in esi avem pozitia curenta
-
//in eax avem minimul, in edx avem pozitia minimului
-
mov eax,[esi]
-
mov edx,ebx
-
//ecx va fi contorul celui de-al doilea for
-
mov ecx,ebx
-
inc ecx
-
add esi,4
-
for_mic:
-
cmp ecx,[ebp+12]
-
je stop
-
mov edi,[esi]
-
cmp edi,eax
-
jb schimba
-
jmp continua
-
schimba:
-
mov eax,[esi]
-
mov edx,ecx
-
jmp continua
-
continua:
-
add esi,4
-
inc ecx
-
jmp for_mic
-
stop:
-
mov esi,[ebp+8]
-
mov eax,ebx
-
shl eax,2
-
add esi,eax
-
mov edi,[ebp+8]
-
mov eax,edx
-
shl eax,2
-
add edi,eax
-
//in esi si edi am cele 2 adrese ale elementelor ce trebuie schimbate
-
-
push dword ptr [esi]
-
push dword ptr [edi]
-
pop dword ptr [esi]
-
pop dword ptr [edi]
-
-
inc ebx
-
jmp for_mare
-
gata:
-
-
}
-
}
-
-
-
int main()
-
{
-
int n,i;
-
n=5;
-
v[0]=10;v[1]=2;v[2]=1;v[3]=5;v[4]=6;
-
Naiv_Sort(v,n);
-
for(i=0;i<n;i++) printf("%d ",v[i]);
-
getchar();
-
return 0;
-
}