交换a,b值的疑问
#include <iostream>
using namespace std;
void MySwap(int& a,int& b)
{
_asm {
mov eax,a
mov ebx,b
xor ebx,eax
xor eax,ebx
xor ebx,eax
mov a,eax
mov b,ebx
}
}
int main()
{
int a=5,b=10;
MySwap(a,b);
printf("a=%d,b=%d\n" ,a,b);
}
请分析一下输出结果。
参考答案:首先,不清楚引用最终怎么实现的,另外不清楚汇编与C语言混用时怎么返回数值,所以这个问题很难呀。试验一:
#include <iostream>
using namespace std;
void MySwap(int& a,int& b)
{
cout<<(long)(&a)<<","<<(long)(&b)<<endl;
_asm {
mov eax,a
mov ebx,b
xor ebx,eax
xor eax,ebx
xor ebx,eax
mov a,eax
mov b,ebx
}
cout<<(long)(&a)<<","<<(long)(&b)<<endl;
}
int main()
{
int a=5,b=10;
cout<<(long)(&a)<<","<<(long)(&b)<<endl;
MySwap(a,b);
cout<<(long)(&a)<<","<<(long)(&b)<<endl;
printf("a=%d,b=%d\n" ,a,b);
}
看一下这个运行结果估计应该有所启发吧!在程序返回时,地址又还原了!我推测引用实现时,只是把各自指向的值交换,而地址不变,程序中的ASM恰恰把它们的地址交换了,而返回时,地址又被还原所以造成没有交换数值。
试验二:
#include <iostream>
using namespace std;
void MySwap(int* a,int* b)
{
// cout<<(long)(&a)<<","<<(long)(&b)<<endl;
cout<<(long)(a)<<","<<(long)(b)<<endl;
_asm {
mov eax,a
mov ebx,b
xor ebx,eax
xor eax,ebx
xor ebx,eax
mov a,eax
mov b,ebx
}
//cout<<(long)(&a)<<","<<(long)(&b)<<endl;
cout<<(long)(a)<<","<<(long)(b)<<endl;
}
int main()
{
int a=5,b=10;
cout<<(long)(&a)<<","<<(long)(&b)<<endl;
MySwap(&a,&b);
cout<<(long)(&a)<<","<<(long)(&b)<<endl;
printf("a=%d,b=%d\n" ,a,b);
}
试验结果与一相同,所以我认为是ASM与C混合的机制造成的,为了防止汇编出错,所有地址要还原。
希望能对你有点启发吧!你也运行一下我改的例子,我也关注此问题中。。。
下面是反汇编的代码:
--- D:\My Documents\code\rubish\asm.cpp ------------------------------------------------------------------------------------------------------------------
1: #include <iostream>
2:
3: using namespace std;
4:
5: void MySwap(int&a,int&b)
6: {
*********** push ebp
*********** mov ebp,esp
*********** sub esp,40h
*********** push ebx
*********** push esi
*********** push edi
*********** lea edi,[ebp-40h]
0040158C mov ecx,10h
*********** mov eax,0CCCCCCCCh
*********** rep stos dword ptr [edi]
7: cout<<(long)(&a)<<","<<(long)(&b)<<endl;
*********** push offset @ILT+195(std::endl) (004010c8)
0040159D mov eax,dword ptr [ebp+0Ch]
004015A0 push eax
004015A1 push offset string "," (0046c01c)
004015A6 mov ecx,dword ptr [ebp+8]
004015A9 push ecx
004015AA mov ecx,offset std::cout (004777f0)
004015AF call @ILT+245(std::basic_ostream<char,std::char_traits<char> >::operator<<) (004010fa)
004015B4 push eax
004015B5 call @ILT+640(std::operator<<) (***********)
004015BA add esp,8
004015BD mov ecx,eax
004015BF call @ILT+245(std::basic_ostream<char,std::char_traits<char> >::operator<<) (004010fa)
004015C4 mov ecx,eax
004015C6 call @ILT+475(std::basic_ostream<char,std::char_traits<char> >::operator<<) (004011e0)
8: // cout<<(long)(a)<<","<<(long)(b)<<endl;
9:
10: _asm {
11: mov eax,a
004015CB mov eax,dword ptr [ebp+8]
12: mov ebx,b
004015CE mov ebx,dword ptr [ebp+0Ch]
13: xor ebx,eax
004015D1 xor ebx,eax
14: xor eax,ebx
004015D3 xor eax,ebx
15: xor ebx,eax
004015D5 xor ebx,eax
16: mov a,eax
004015D7 mov dword ptr [ebp+8],eax
17: mov b,ebx
004015DA mov dword ptr [ebp+0Ch],ebx
18: }
19: /* int c;
20: c=a;
21: a=b;
22: b=c;*/
23: cout<<(long)(&a)<<","<<(long)(&b)<<endl;
004015DD push offset @ILT+195(std::endl) (004010c8)
004015E2 mov edx,dword ptr [ebp+0Ch]
004015E5 push edx
004015E6 push offset string "," (0046c01c)
004015EB mov eax,dword ptr [ebp+8]
004015EE push eax
004015EF mov ecx,offset std::cout (004777f0)
004015F4 call @ILT+245(std::basic_ostream<char,std::char_traits<char> >::operator<<) (004010fa)
004015F9 push eax
004015FA call @ILT+640(std::operator<<) (***********)
004015FF add esp,8
*********** mov ecx,eax
*********** call @ILT+245(std::basic_ostream<char,std::char_traits<char> >::operator<<) (004010fa)
*********** mov ecx,eax
0040160B call @ILT+475(std::basic_ostream<char,std::char_traits<char> >::operator<<) (004011e0)
24: //cout<<(long)(a)<<","<<(long)(b)<<endl;
25: }
*********** pop edi
*********** pop esi
*********** pop ebx
*********** add esp,40h
*********** cmp ebp,esp
*********** call __chkesp (00420a50)
0040161D mov esp,ebp
0040161F pop ebp
*********** ret
--- D:\My Documents\code\rubish\asm.cpp ------------------------------------------------------------------------------------------------------------------
26:
27: int main()
28: {
*********** push ebp
*********** mov ebp,esp
*********** sub esp,48h
*********** push ebx
*********** push esi
*********** push edi
*********** lea edi,[ebp-48h]
0040165C mov ecx,12h
*********** mov eax,0CCCCCCCCh
*********** rep stos dword ptr [edi]
29: int a=5,b=10;
*********** mov dword ptr [ebp-4],5
0040166F mov dword ptr [ebp-8],0Ah
30:
31: cout<<(long)(&a)<<","<<(long)(&b)<<endl;
*********** push offset @ILT+195(std::endl) (004010c8)
0040167B lea eax,[ebp-8]
0040167E push eax
0040167F push offset string "," (0046c01c)
*********** lea ecx,[ebp-4]
*********** push ecx
*********** mov ecx,offset std::cout (004777f0)
0040168D call @ILT+245(std::basic_ostream<char,std::char_traits<char> >::operator<<) (004010fa)
*********** push eax
*********** call @ILT+640(std::operator<<) (***********)
*********** add esp,8
0040169B mov ecx,eax
0040169D call @ILT+245(std::basic_ostream<char,std::char_traits<char> >::operator<<) (004010fa)
004016A2 mov ecx,eax
004016A4 call @ILT+475(std::basic_ostream<char,std::char_traits<char> >::operator<<) (004011e0)
32: MySwap(a,b);
004016A9 lea edx,[ebp-8]
004016AC push edx ;b
004016AD lea eax,[ebp-4]
004016B0 push eax ;a
004016B1 call @ILT+660(MySwap) (***********)
004016B6 add esp,8
33: cout<<(long)(&a)<<","<<(long)(&b)<<endl;
004016B9 push offset @ILT+195(std::endl) (004010c8)
004016BE lea ecx,[ebp-8]
004016C1 push ecx
004016C2 push offset string "," (0046c01c)
004016C7 lea edx,[ebp-4]
004016CA push edx
004016CB mov ecx,offset std::cout (004777f0)
004016D0 call @ILT+245(std::basic_ostream<char,std::char_traits<char> >::operator<<) (004010fa)
004016D5 push eax
004016D6 call @ILT+640(std::operator<<) (***********)
004016DB add esp,8
004016DE mov ecx,eax
004016E0 call @ILT+245(std::basic_ostream<char,std::char_traits<char> >::operator<<) (004010fa)
004016E5 mov ecx,eax
004016E7 call @ILT+475(std::basic_ostream<char,std::char_traits<char> >::operator<<) (004011e0)
34: printf("a=%d,b=%d\n" ,a,b);
004016EC mov eax,dword ptr [ebp-8]
004016EF push eax
004016F0 mov ecx,dword ptr [ebp-4]
004016F3 push ecx
004016F4 push offset string "a=%d,b=%d\n" (0046c020)
004016F9 call printf (00420a90)
004016FE add esp,0Ch
35: }
*********** pop edi
*********** pop esi
*********** pop ebx
*********** add esp,48h
*********** cmp ebp,esp
*********** call __chkesp (00420a50)
0040170E mov esp,ebp
*********** pop ebp
*********** ret