先记录下题外话:CALL指令将紧接在他之后的指令压入堆栈的顶部,但是esp的值并不发生变化,等待该过程执行完毕之后,执行RET指令,将程序的控制权还给之前压入堆栈的call之后的第一条指令的地址。结束函数的执行。例外的是并不是多有的RET指令都表示函数的结束,同时有一点要记得,函数可能并非只有一个出口点。对不?
好了进入正题:
C++代码如下
#include<iostream>
using namespace std;
void test()
{
for(int a=0;a<10;a++)
{
cout<<a<<endl;
}
cout<<"dsadasdas\n";
}
int _tmain(int argc, _TCHAR* argv[])
{
test();
test();
return 0;
}
反汇编之后:
?
.text:00401000 ; int __cdecl wmain(int argc, wchar_t **argv)
.text:00401000 _wmain proc near ; CODE XREF: __tmainCRTStartup+11Dp
.text:00401000
.text:00401000 argc = dword ptr 8
.text:00401000 argv = dword ptr 0Ch
.text:00401000
.text:00401000 mov eax, ds:__imp_?cout@std@@3V?$basic_ostream@DU?$char_traits@D@std@@@1@A ; std::basic_ostream<char,std::char_traits<char>> std::cout
.text:00401005 push esi
.text:00401006 push offset _Val ; "just a test\n"
.text:0040100B push eax ; _Ostr
.text:0040100C call ??$?6U?$char_traits@D@std@@@std@@YAAAV?$basic_ostream@DU?$char_traits@D@std@@@0@AAV10@PBD@Z ; std::operator<<<std::char_traits<char>>(std::basic_ostream<char,std::char_traits<char>> &,char const *)
.text:00401011 add esp, 8
.text:00401014 xor esi, esi
.text:00401016 jmp short loc_401020
.text:00401016 ; ---------------------------------------------------------------------------
.text:00401018 align 10h
.text:00401020
.text:00401020 loc_401020: ; CODE XREF: _wmain+16j
.text:00401020 ; _wmain+40j
.text:00401020 mov ecx, ds:__imp_?endl@std@@YAAAV?$basic_ostream@DU?$char_traits@D@std@@@1@AAV21@@Z ; std::endl(std::basic_ostream<char,std::char_traits<char>> &)
.text:00401026 push ecx
.text:00401027 mov ecx, ds:__imp_?cout@std@@3V?$basic_ostream@DU?$char_traits@D@std@@@1@A ; std::basic_ostream<char,std::char_traits<char>> std::cout
.text:0040102D push esi
.text:0040102E call ds:__imp_??6?$basic_ostream@DU?$char_traits@D@std@@@std@@QAEAAV01@H@Z ; std::basic_ostream<char,std::char_traits<char>>::operator<<(int)
.text:00401034 mov ecx, eax
.text:00401036 call ds:__imp_??6?$basic_ostream@DU?$char_traits@D@std@@@std@@QAEAAV01@P6AAAV01@AAV01@@Z@Z ; std::basic_ostream<char,std::char_traits<char>>::operator<<(std::basic_ostream<char,std::char_traits<char>> & (*)(std::basic_ostream<char,std::char_traits<char>> &))
.text:0040103C inc esi
.text:0040103D cmp esi, 0Ah
.text:00401040 jl short loc_401020
.text:00401042 mov edx, ds:__imp_?cout@std@@3V?$basic_ostream@DU?$char_traits@D@std@@@1@A ; std::basic_ostream<char,std::char_traits<char>> std::cout
.text:00401048 push offset aDsadasdas ; "dsadasdas\n"
.text:0040104D push edx ; _Ostr
.text:0040104E call ??$?6U?$char_traits@D@std@@@std@@YAAAV?$basic_ostream@DU?$char_traits@D@std@@@0@AAV10@PBD@Z ; std::operator<<<std::char_traits<char>>(std::basic_ostream<char,std::char_traits<char>> &,char const *)
.text:00401053 add esp, 8
.text:00401056 xor esi, esi
.text:00401058 jmp short loc_401060
.text:00401058 ; ---------------------------------------------------------------------------
.text:0040105A align 10h
.text:00401060
.text:00401060 loc_401060: ; CODE XREF: _wmain+58j
.text:00401060 ; _wmain+7Fj
.text:00401060 mov eax, ds:__imp_?endl@std@@YAAAV?$basic_ostream@DU?$char_traits@D@std@@@1@AAV21@@Z ; std::endl(std::basic_ostream<char,std::char_traits<char>> &)
.text:00401065 mov ecx, ds:__imp_?cout@std@@3V?$basic_ostream@DU?$char_traits@D@std@@@1@A ; std::basic_ostream<char,std::char_traits<char>> std::cout
.text:0040106B push eax
.text:0040106C push esi
.text:0040106D call ds:__imp_??6?$basic_ostream@DU?$char_traits@D@std@@@std@@QAEAAV01@H@Z ; std::basic_ostream<char,std::char_traits<char>>::operator<<(int)
.text:00401073 mov ecx, eax
.text:00401075 call ds:__imp_??6?$basic_ostream@DU?$char_traits@D@std@@@std@@QAEAAV01@P6AAAV01@AAV01@@Z@Z ; std::basic_ostream<char,std::char_traits<char>>::operator<<(std::basic_ostream<char,std::char_traits<char>> & (*)(std::basic_ostream<char,std::char_traits<char>> &))
.text:0040107B inc esi
.text:0040107C cmp esi, 0Ah
.text:0040107F jl short loc_401060
.text:00401081 mov ecx, ds:__imp_?cout@std@@3V?$basic_ostream@DU?$char_traits@D@std@@@1@A ; std::basic_ostream<char,std::char_traits<char>> std::cout
.text:00401087 push offset aDsadasdas ; "dsadasdas\n"
.text:0040108C push ecx ; _Ostr
.text:0040108D call ??$?6U?$char_traits@D@std@@@std@@YAAAV?$basic_ostream@DU?$char_traits@D@std@@@0@AAV10@PBD@Z ; std::operator<<<std::char_traits<char>>(std::basic_ostream<char,std::char_traits<char>> &,char const *)
.text:00401092 add esp, 8
.text:00401095 xor eax, eax
.text:00401097 pop esi
.text:00401098 retn
.text:00401098 _wmain endp
test函数是在loc_401020和401056之间,在C语言中test是一个函数,但经过反编译之后则变成一段程序序列,调用了两次,虽然调用了两次,但是程序也编译了两次,两次调用并非使用了一段指令序列,我想这就是编译器自行实现了内联函数吧