-
-
[旧帖] [原创]Debug与Release的真正区别 0.00雪花
-
发表于: 2013-1-17 01:41 1518
-
这个是我第二篇帖子,有什么不对请及时跟我说,高手你也不要栗色你那点技术。
以前读书的时候只知道Debug是在调试的时候用的,而Release是在发行版的时候用。到底它们有什么不同根本不清楚。就像小孩子一样,大人叫她干什么,她就干什么。从来不会为为什么这么做。(我说的是我那个时代,现在的孩子可能不同)。
最近看了一些书知道,下面扫盲下:
Release是经过优化的,不管用什么高级语言开发软件汇编生成的可执行文件都是“指令形式”。
像在Debug版本下一个函数(为什么讲函数原因是我们在c语言的main本身就是函数)调用
都是有着几个步骤
00412D90 push ebp //保存用于放回ret地址,函数调用形式都是先保存当前地址,
//然后跳动要执行函数,执行完,取出保存先前地址,返回到主函数中去。
00412D91 mov ebp,esp //保存栈顶地址esp.堆栈是先进后出原则
00412D93 sub esp,0E8h //在堆栈分配空间给局部变量
00412D99 push ebx //保存ebx,esi,edi
00412D9A push esi
00412D9B push edi
00412D9C lea edi,[ebp-0E8h] //把分配的首地址赋值给edi,现在edi就是ebp-0e8h
00412DA2 mov ecx,3Ah //循环次数一般都是跟rep,loop等连用
00412DA7 mov eax,0CCCCCCCCh //初始化局部变量0cch就是机器指令 int 3中断指令,
//表示局部变量是不可以执行的,假如执行就出现错误
00412DAC rep stos dword ptr es:[edi] //重复的把edi所指的内容赋值为0CCCCCCCCh
而Release下很多东西都是精简的所以很多东西可能都被省略:
比如在内部变量在比较少的时候直接用的寄存器,这边在堆栈中内部划分代码就被省略掉了,把内存变量初始化int 3的代码也被省略 取参数的时候不会放在内部变量中,而是直接用esp取。同时又的时候ebp根本就没有用。
下面是经验汇编代码举例
push eax
push esi
call Myfuction//调用函数
add esp ,8
下面看看下函数在debug跟Release是什么样子的
那个计较难的算法吧(这边肯定有人会说这有什么难)
int fuction(int a[3][3],int b[3][3],int c[3][3])
{
int i,j;
for ( i=0;i<3;i++)
{
for (j=0;j<3;j++)
{
c[i][j]=a[i][0]*b[0][j]+a[i][1]*b[1][j]+a[i][2]*b[2][j];
}
}
return 0;
}
在c语言清楚我想大家跟我所想一样----TMD太简单了
但是汇编下你在看看
--- Debug版本------------------------------------------
int fuction(int a[3][3],int b[3][3],int c[3][3])
{
00413440 push ebp
00413441 mov ebp,esp
00413443 sub esp,0D8h
00413449 push ebx
0041344A push esi
0041344B push edi
0041344C lea edi,[ebp-0D8h]
00413452 mov ecx,36h
00413457 mov eax,0CCCCCCCCh
0041345C rep stos dword ptr es:[edi]
int i,j;
for ( i=0;i<3;i++)
0041345E mov dword ptr [i],0
00413465 jmp fuction+30h (413470h) //第一次执行的时候i=o后执行判断
00413467 mov eax,dword ptr [i]
0041346A add eax,1
0041346D mov dword ptr [i],eax
00413470 cmp dword ptr [i],3
00413474 jge fuction+0AEh (4134EEh)
{
for (j=0;j<3;j++)
00413476 mov dword ptr [j],0
0041347D jmp fuction+48h (413488h)
0041347F mov eax,dword ptr [j]
00413482 add eax,1
00413485 mov dword ptr [j],eax
00413488 cmp dword ptr [j],3
0041348C jge fuction+0A9h (4134E9h)
{
c[i][j]=a[i][0]*b[0][j]+a[i][1]*b[1][j]+a[i][2]*b[2][j];
0041348E mov eax,dword ptr [i]
00413491 imul eax,eax,0Ch //这边 i*3(一个是四字节)3就是12十六进制就是0ch
00413494 mov ecx,dword ptr [a] //变量a
00413497 mov edx,dword ptr [j]
0041349A mov esi,dword ptr //变量b
0041349D mov eax,dword ptr [ecx+eax]
004134A0 imul eax,dword ptr [esi+edx*4]
004134A4 mov ecx,dword ptr [i]
004134A7 imul ecx,ecx,0Ch
004134AA mov edx,dword ptr [a]
004134AD mov esi,dword ptr [j]
004134B0 mov edi,dword ptr
004134B3 mov ecx,dword ptr [edx+ecx+4]
004134B7 imul ecx,dword ptr [edi+esi*4+0Ch]
004134BC add eax,ecx
004134BE mov edx,dword ptr [i]
004134C1 imul edx,edx,0Ch
004134C4 mov ecx,dword ptr [a]
004134C7 mov esi,dword ptr [j]
004134CA mov edi,dword ptr
004134CD mov edx,dword ptr [ecx+edx+8]
004134D1 imul edx,dword ptr [edi+esi*4+18h]
004134D6 add eax,edx
004134D8 mov ecx,dword ptr [i]
004134DB imul ecx,ecx,0Ch
004134DE add ecx,dword ptr [c]
004134E1 mov edx,dword ptr [j]
004134E4 mov dword ptr [ecx+edx*4],eax
}
004134E7 jmp fuction+3Fh (41347Fh)
}
004134E9 jmp fuction+27h (413467h)
return 0;
004134EE xor eax,eax
}
004134F0 pop edi
004134F1 pop esi
004134F2 pop ebx
004134F3 mov esp,ebp
004134F5 pop ebp
004134F6 ret
这个一般可能都能看的懂
--------------------------你在看看Release------------------
int myfunction ( int a[3][3],int b[3][3],int c[3][3])
{
int i,j;
for(i=0;i<3;i++)
00401000 mov eax,dword ptr [esp+4h] //eax=a[0][0],
00401004 mov edx,dword ptr [esp+8h] //ecx=b[0][0];
00401008 mov ecx ,dword ptr [esp+0ch] //edx=c[0][0];
0040100e add eax,4 //eax=eax+4==a[0][1];
00401011 push edi //保存edi
00401012 add edx,8; //adx=adx+8==c[0][2];
00401015 esi=3 //用于循环的次数
0040101a lea ebx,[ebx] //无效指令
00401020 mov ebx,dword ptr [eax] //把a[0][1]的值赋值给ebx
00401022 imul ebx,dword ptr [ecx+och] //就是把a[0][1]*b[1][0]赋值与abx
//相当:i=0,j=0时候a[i][0]*b[1][j]
00401026 mov edi ,dword ptr [ecx+18h] //把b[2][0]赋值给edi
00401029 imul edi,dword ptr [eax+4] //b[2][0]*a[0][2]赋值给edi
0040102d add edi,ebx //edi=edi+ebx相当于a[0][1]*b[1][0]+b[2][0]*a[0][2]
//相当:i=0,j=0时候a[i][0]*b[1][j]+a[i][2]*b[2][j]
0040102f mov ebx,dword ptr [eax-4] //a[0][0]赋值给ebx
00401032 imul ebx,dword ptr [ecx] //a[0][0]*b[0][0]赋值给ebx
00401035 add edi,ebx //这是的的edi就是a[0][1]*b[1][0]+b[2][0]*a[0][2]+a[0][0]*b[0][0]
//相当:i=0,j=0时候a[i][0]*b[0][j]+a[i][1]*b[1][j]+a[i][2]*b[2][j]循环一次
00401037 mov dword ptr [edx-8],edi //给c[0][0]赋值
0040103a mov ebx,word ptr [eax] //a[0][0]赋值给ebx
0040103c imul ebx,dword ptr [ecx+10h] //ebx==a[0][1]*b[1][1]
00401040 mov edi,dword ptr[ecx+1ch] //edi==b[2][1]
00401043 imul edi,dword ptr [eax+4] //edi==a[0][2]*b[2][1]
00401047 add edi,ebx //edi=edi+ebx==a[0][1]b[1][1]+a[0][2]*b[2][1]
00401049 mov ebx.dword ptr[eax-4] //ebx=a[0][0]
0040104c imul ebx,dword prt [ecx+4] //ebx=ebx乘以ecx+4地处保存的值就是b[0][1]
//ebx==a[0][0]*b[0][1]
00401050 add edi ,ebx //edi==a[0][1]b[1][1]+a[0][2]*b[2][1]+a[0][0]*b[0][1]
//相当于i=0,j=1的.......
00401052 mov dword ptr [edx-4],edi //把edi的值保存到才c[0][1]中
00401055 mov ebx,word ptr [eax+4] //ebx==a[0][2]
00401058 imul ebx,dword ptr [ecx+20h] //ebx=ebx*[ecx+20h]等于a[0][2]*b[2][2]
0040105c mov edi dword ptr [ecx+14h] //edi=b[1][2]
0040105f imul edi dword ptr [eax] //edi=edi*[eax]==edi=b[1][2]*a[0][1]
00401062 add edi,ebx //edi=edi+ebx==a[0][2]*b[2][2]+b[1][2]*a[0][1]
00401064 mov ebx,dword ptr [eax-4] //ebx=a[0][0]
00401067 imul ebx,dword ptr [ecx+8] //ebx=ebx*[ecx+8]=a[0][0]*b[0][2]
0040106b add edi,ebx
0040106d mov dword ptr [edx],edi
//相当于i=0,j=2............
0040106d add eax,och //eax=a[0][1]+och=a[1][1];
00401072 add edx,och //edx=c[0][0]+och=c[1][0]
00401075 dec esi //esi-1==3-1=2
00401076 jne myfuction+20h(401020h) //不等于零的时候跳转
00401078 pop edi
00401079 pop esi
}
return 0;
0040107a xor eax,eax
0040107c pop ebx
为了写这个注释我花了差不多1小时。
以前读书的时候只知道Debug是在调试的时候用的,而Release是在发行版的时候用。到底它们有什么不同根本不清楚。就像小孩子一样,大人叫她干什么,她就干什么。从来不会为为什么这么做。(我说的是我那个时代,现在的孩子可能不同)。
最近看了一些书知道,下面扫盲下:
Release是经过优化的,不管用什么高级语言开发软件汇编生成的可执行文件都是“指令形式”。
像在Debug版本下一个函数(为什么讲函数原因是我们在c语言的main本身就是函数)调用
都是有着几个步骤
00412D90 push ebp //保存用于放回ret地址,函数调用形式都是先保存当前地址,
//然后跳动要执行函数,执行完,取出保存先前地址,返回到主函数中去。
00412D91 mov ebp,esp //保存栈顶地址esp.堆栈是先进后出原则
00412D93 sub esp,0E8h //在堆栈分配空间给局部变量
00412D99 push ebx //保存ebx,esi,edi
00412D9A push esi
00412D9B push edi
00412D9C lea edi,[ebp-0E8h] //把分配的首地址赋值给edi,现在edi就是ebp-0e8h
00412DA2 mov ecx,3Ah //循环次数一般都是跟rep,loop等连用
00412DA7 mov eax,0CCCCCCCCh //初始化局部变量0cch就是机器指令 int 3中断指令,
//表示局部变量是不可以执行的,假如执行就出现错误
00412DAC rep stos dword ptr es:[edi] //重复的把edi所指的内容赋值为0CCCCCCCCh
而Release下很多东西都是精简的所以很多东西可能都被省略:
比如在内部变量在比较少的时候直接用的寄存器,这边在堆栈中内部划分代码就被省略掉了,把内存变量初始化int 3的代码也被省略 取参数的时候不会放在内部变量中,而是直接用esp取。同时又的时候ebp根本就没有用。
下面是经验汇编代码举例
push eax
push esi
call Myfuction//调用函数
add esp ,8
下面看看下函数在debug跟Release是什么样子的
那个计较难的算法吧(这边肯定有人会说这有什么难)
int fuction(int a[3][3],int b[3][3],int c[3][3])
{
int i,j;
for ( i=0;i<3;i++)
{
for (j=0;j<3;j++)
{
c[i][j]=a[i][0]*b[0][j]+a[i][1]*b[1][j]+a[i][2]*b[2][j];
}
}
return 0;
}
在c语言清楚我想大家跟我所想一样----TMD太简单了
但是汇编下你在看看
--- Debug版本------------------------------------------
int fuction(int a[3][3],int b[3][3],int c[3][3])
{
00413440 push ebp
00413441 mov ebp,esp
00413443 sub esp,0D8h
00413449 push ebx
0041344A push esi
0041344B push edi
0041344C lea edi,[ebp-0D8h]
00413452 mov ecx,36h
00413457 mov eax,0CCCCCCCCh
0041345C rep stos dword ptr es:[edi]
int i,j;
for ( i=0;i<3;i++)
0041345E mov dword ptr [i],0
00413465 jmp fuction+30h (413470h) //第一次执行的时候i=o后执行判断
00413467 mov eax,dword ptr [i]
0041346A add eax,1
0041346D mov dword ptr [i],eax
00413470 cmp dword ptr [i],3
00413474 jge fuction+0AEh (4134EEh)
{
for (j=0;j<3;j++)
00413476 mov dword ptr [j],0
0041347D jmp fuction+48h (413488h)
0041347F mov eax,dword ptr [j]
00413482 add eax,1
00413485 mov dword ptr [j],eax
00413488 cmp dword ptr [j],3
0041348C jge fuction+0A9h (4134E9h)
{
c[i][j]=a[i][0]*b[0][j]+a[i][1]*b[1][j]+a[i][2]*b[2][j];
0041348E mov eax,dword ptr [i]
00413491 imul eax,eax,0Ch //这边 i*3(一个是四字节)3就是12十六进制就是0ch
00413494 mov ecx,dword ptr [a] //变量a
00413497 mov edx,dword ptr [j]
0041349A mov esi,dword ptr //变量b
0041349D mov eax,dword ptr [ecx+eax]
004134A0 imul eax,dword ptr [esi+edx*4]
004134A4 mov ecx,dword ptr [i]
004134A7 imul ecx,ecx,0Ch
004134AA mov edx,dword ptr [a]
004134AD mov esi,dword ptr [j]
004134B0 mov edi,dword ptr
004134B3 mov ecx,dword ptr [edx+ecx+4]
004134B7 imul ecx,dword ptr [edi+esi*4+0Ch]
004134BC add eax,ecx
004134BE mov edx,dword ptr [i]
004134C1 imul edx,edx,0Ch
004134C4 mov ecx,dword ptr [a]
004134C7 mov esi,dword ptr [j]
004134CA mov edi,dword ptr
004134CD mov edx,dword ptr [ecx+edx+8]
004134D1 imul edx,dword ptr [edi+esi*4+18h]
004134D6 add eax,edx
004134D8 mov ecx,dword ptr [i]
004134DB imul ecx,ecx,0Ch
004134DE add ecx,dword ptr [c]
004134E1 mov edx,dword ptr [j]
004134E4 mov dword ptr [ecx+edx*4],eax
}
004134E7 jmp fuction+3Fh (41347Fh)
}
004134E9 jmp fuction+27h (413467h)
return 0;
004134EE xor eax,eax
}
004134F0 pop edi
004134F1 pop esi
004134F2 pop ebx
004134F3 mov esp,ebp
004134F5 pop ebp
004134F6 ret
这个一般可能都能看的懂
--------------------------你在看看Release------------------
int myfunction ( int a[3][3],int b[3][3],int c[3][3])
{
int i,j;
for(i=0;i<3;i++)
00401000 mov eax,dword ptr [esp+4h] //eax=a[0][0],
00401004 mov edx,dword ptr [esp+8h] //ecx=b[0][0];
00401008 mov ecx ,dword ptr [esp+0ch] //edx=c[0][0];
0040100e add eax,4 //eax=eax+4==a[0][1];
00401011 push edi //保存edi
00401012 add edx,8; //adx=adx+8==c[0][2];
00401015 esi=3 //用于循环的次数
0040101a lea ebx,[ebx] //无效指令
00401020 mov ebx,dword ptr [eax] //把a[0][1]的值赋值给ebx
00401022 imul ebx,dword ptr [ecx+och] //就是把a[0][1]*b[1][0]赋值与abx
//相当:i=0,j=0时候a[i][0]*b[1][j]
00401026 mov edi ,dword ptr [ecx+18h] //把b[2][0]赋值给edi
00401029 imul edi,dword ptr [eax+4] //b[2][0]*a[0][2]赋值给edi
0040102d add edi,ebx //edi=edi+ebx相当于a[0][1]*b[1][0]+b[2][0]*a[0][2]
//相当:i=0,j=0时候a[i][0]*b[1][j]+a[i][2]*b[2][j]
0040102f mov ebx,dword ptr [eax-4] //a[0][0]赋值给ebx
00401032 imul ebx,dword ptr [ecx] //a[0][0]*b[0][0]赋值给ebx
00401035 add edi,ebx //这是的的edi就是a[0][1]*b[1][0]+b[2][0]*a[0][2]+a[0][0]*b[0][0]
//相当:i=0,j=0时候a[i][0]*b[0][j]+a[i][1]*b[1][j]+a[i][2]*b[2][j]循环一次
00401037 mov dword ptr [edx-8],edi //给c[0][0]赋值
0040103a mov ebx,word ptr [eax] //a[0][0]赋值给ebx
0040103c imul ebx,dword ptr [ecx+10h] //ebx==a[0][1]*b[1][1]
00401040 mov edi,dword ptr[ecx+1ch] //edi==b[2][1]
00401043 imul edi,dword ptr [eax+4] //edi==a[0][2]*b[2][1]
00401047 add edi,ebx //edi=edi+ebx==a[0][1]b[1][1]+a[0][2]*b[2][1]
00401049 mov ebx.dword ptr[eax-4] //ebx=a[0][0]
0040104c imul ebx,dword prt [ecx+4] //ebx=ebx乘以ecx+4地处保存的值就是b[0][1]
//ebx==a[0][0]*b[0][1]
00401050 add edi ,ebx //edi==a[0][1]b[1][1]+a[0][2]*b[2][1]+a[0][0]*b[0][1]
//相当于i=0,j=1的.......
00401052 mov dword ptr [edx-4],edi //把edi的值保存到才c[0][1]中
00401055 mov ebx,word ptr [eax+4] //ebx==a[0][2]
00401058 imul ebx,dword ptr [ecx+20h] //ebx=ebx*[ecx+20h]等于a[0][2]*b[2][2]
0040105c mov edi dword ptr [ecx+14h] //edi=b[1][2]
0040105f imul edi dword ptr [eax] //edi=edi*[eax]==edi=b[1][2]*a[0][1]
00401062 add edi,ebx //edi=edi+ebx==a[0][2]*b[2][2]+b[1][2]*a[0][1]
00401064 mov ebx,dword ptr [eax-4] //ebx=a[0][0]
00401067 imul ebx,dword ptr [ecx+8] //ebx=ebx*[ecx+8]=a[0][0]*b[0][2]
0040106b add edi,ebx
0040106d mov dword ptr [edx],edi
//相当于i=0,j=2............
0040106d add eax,och //eax=a[0][1]+och=a[1][1];
00401072 add edx,och //edx=c[0][0]+och=c[1][0]
00401075 dec esi //esi-1==3-1=2
00401076 jne myfuction+20h(401020h) //不等于零的时候跳转
00401078 pop edi
00401079 pop esi
}
return 0;
0040107a xor eax,eax
0040107c pop ebx
为了写这个注释我花了差不多1小时。
[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!
赞赏
看原图
赞赏
雪币:
留言: