| 网站首页 | 业界新闻 | 小组 | 威客 | 人才 | 下载频道 | 博客 | 代码贴 | 在线编程 | 编程论坛
欢迎加入我们,一同切磋技术
用户名:   
 
密 码:  
共有 1395 人关注过本帖
标题:呕心沥血两小时 终于弄的差不多了
取消只看楼主 加入收藏
信箱有效
Rank: 13Rank: 13Rank: 13Rank: 13
等 级:蒙面侠
威 望:9
帖 子:1102
专家分:4268
注 册:2012-6-19
结帖率:100%
收藏
 问题点数:0 回复次数:1 
呕心沥血两小时 终于弄的差不多了
好累啊 眼都花了。。。

最近我连睡觉都拿汇编书当枕头 ,果然有点效果。
那个帖子太长了 我就自己发个小贴。
编译的EXE在 https://bbs.bccn.net/thread-375040-1-1.html  一楼。

完全以zklhp编译的EXE为目标,如果用其他的编译器,结果大概会有不同。
比如如果用VC,或者大概也许不会有and   esp, 0FFFFFFF0h这个使esp后4位为0。
即使用同一个编译器 ,加上不同的编译参数,结果也可能不同。比如是否使用ebp指针。

复制一遍
程序代码:
#include <stdio.h>
#include <string.h>

int main(void)
{
    char a[64] = {0};
    strcpy(a, "我用这个数组放一个字符串");
    printf("a是:%s\n", a);
  
    {
        //这是个大括号里面
        char b[64] = {0};
        strcpy(b, a);
        printf("b是:%s\n", b);
    }
    //理论上到这里b就释放了
  
    char c[64] = "这里再有一个字符串应该是不增加堆栈大小才对";
    printf("c是:%s\n", c);

    return 0;
}


分析参数和局部变量这些问题,如果仅靠看源码或者凭已有知识进行的想象,还是很难了解透彻。
编译好EXE以后,进行反汇编,这个是最直接最快捷最有效的了。

下面就是我花了2个小时一条一条琢磨出来的。
这些指令 ,单单的任挑一条出来,都可以查百度查资料知道是什么意思,
困难的是几条指令合起来是什么意思。。。

都进行了分段和注释,明天再总结,今天头
程序代码:
.text:004013B7 ; Attributes: bp-based frame
.text:004013B7
.text:004013B7 sub_4013B7      proc near               ; CODE XREF: sub_401000+B4p
.text:004013B7
.text:004013B7 var_DC          = dword ptr -0DCh
.text:004013B7 var_D8          = dword ptr -0D8h
.text:004013B7 var_CC          = byte ptr -0CCh
.text:004013B7 var_8C          = byte ptr -8Ch
.text:004013B7 var_61          = byte ptr -61h
.text:004013B7 var_4C          = byte ptr -4Ch
.text:004013B7
.text:004013B7                 push    ebp
.text:004013B8                 mov     ebp, esp
.text:004013BA                 push    edi
.text:004013BB                 push    esi
.text:004013BC                 push    ebx
.text:004013BD                 and     esp, 0FFFFFFF0h        ;调整堆栈指针使之按16字节对齐
.text:004013C0                 sub     esp, 0D0h        ;开辟堆栈空间,大小为D0
.text:004013C6                 call    sub_4019B4



.text:004013CB                 lea     ebx, [esp+0DCh+var_4C]
.text:004013D2                 mov     al, 0            ;填充内容为0
.text:004013D4                 mov     edx, 40h            ;数量40h
.text:004013D9                 mov     edi, ebx
.text:004013DB                 mov     ecx, edx
.text:004013DD                 rep stosb            ;从地址[esp+0DCh+var_4C]开始初始化40h个字节内容为0。




.text:004013DF                 lea     eax, [esp+0DCh+var_4C]
.text:004013E6                 mov     edx, eax
.text:004013E8                 mov     ebx, offset aTSO ; "我用这个数组放一个字符串"
.text:004013ED                 mov     eax, 19h            ;19h个字节的数据
.text:004013F2                 mov     edi, edx
.text:004013F4                 mov     esi, ebx
.text:004013F6                 mov     ecx, eax
.text:004013F8                 rep movsb    ;    ;将19h个字节的字符串数据传送到堆栈地址[esp+0DCh+var_4C]为开始地址。


   
.text:004013FA                 lea     eax, [esp+0DCh+var_4C]
.text:00401401                 mov     [esp+0DCh+var_D8], eax    ;传参数二
.text:00401405                 mov     [esp+0DCh+var_DC], offset aAGS ; "a是:%s\n";传参数一
.text:0040140C                 call    sub_40138C        ;调用printf函数



.text:00401411                 lea     ebx, [esp+0DCh+var_CC]
.text:00401415                 mov     al, 0
.text:00401417                 mov     edx, 40h
.text:0040141C                 mov     edi, ebx
.text:0040141E                 mov     ecx, edx
.text:00401420                 rep stosb    ;用0初始化堆栈地址[esp+0DCh+var_CC]开始的40h个字节的空间。


.text:00401422                 lea     eax, [esp+0DCh+var_4C]
.text:00401429                 mov     [esp+0DCh+var_D8], eax    ;把刚才传送到堆栈内的字符串数据地址作为strcpy的第2参数
.text:0040142D                 lea     eax, [esp+0DCh+var_CC]    ;将刚初始化的40h个字节的堆栈空间首地址作为strcpy的第1参数传递
.text:00401431                 mov     [esp+0DCh+var_DC], eax
.text:00401434                 call    strcpy        ;

   
.text:00401439                 lea     eax, [esp+0DCh+var_CC]   
.text:0040143D                 mov     [esp+0DCh+var_D8], eax        ;传二参
.text:00401441                 mov     [esp+0DCh+var_DC], offset aBGS ; "b是:%s\n"  ;传一参
.text:00401448                 call    sub_40138C    ;调用printf函数



.text:0040144D                 lea     edx, [esp+0DCh+var_8C]
.text:00401451                 mov     ebx, offset aTQOJB ; "这里再有一个字符串应该是不增加堆栈大小?...
.text:00401456                 mov     eax, 2Bh        ;需传送的字节数为2bh
.text:0040145B                 mov     edi, edx        ;目的
.text:0040145D                 mov     esi, ebx        ;源
.text:0040145F                 mov     ecx, eax        ;计数2bh
.text:00401461                 rep movsb        ;把字符串传送至堆栈[esp+0DCh+var_8C]开始的2bh个字节中。




.text:00401463                 lea     ebx, [esp+0DCh+var_61]
.text:00401467                 mov     al, 0
.text:00401469                 mov     edx, 15h
.text:0040146E                 mov     edi, ebx
.text:00401470                 mov     ecx, edx
.text:00401472                 rep stosb    ;用0初始化堆栈地址[esp+0DCh+var_61]开始的15h个字节



.text:00401474                 lea     eax, [esp+0DCh+var_8C]       
.text:00401478                 mov     [esp+0DCh+var_D8], eax            ;传二参
.text:0040147C                 mov     [esp+0DCh+var_DC], offset aCGS ; "c是:%s\n"  ;传一参
.text:00401483                 call    sub_40138C        ;调用printf函数



.text:00401488                 mov     eax, 0return 0


.text:0040148D                 lea     esp, [ebp-0Ch]    ;平衡堆栈
.text:00401490                 pop     ebx
.text:00401491                 pop     esi
.text:00401492                 pop     edi
.text:00401493                 pop     ebp        ;平衡堆栈 对应开头的4个PUSH
.text:00401494                 retn
.text:00401494 sub_4013B7      endp
.text:00401494




搜索更多相关主题的帖子: include 编译器 
2012-08-11 02:29
信箱有效
Rank: 13Rank: 13Rank: 13Rank: 13
等 级:蒙面侠
威 望:9
帖 子:1102
专家分:4268
注 册:2012-6-19
收藏
得分:0 
在c码中,有main函数的3个局部变量。总结一下在堆栈中的形成及位置:

-4c开始40h个字节填0,使用19h个字节写入a数组

-CC开始40h个字节填0,并将19h个字节的a数组复制进来当作b数组

-8c开始2bh个字节被写入数组C。

-61开始15h个字节填0。


源码及实际执行时的形成顺序都是这样abc,但是在堆栈中的排列却是acb

b数组位于堆栈的上方,再上面就是作为printf函数的参数-DC -D8的栈顶了,这2个
位置一直是在被重复覆盖使用的。

大括号中的b数组为什么会处于栈的上方,或许真是因为大括号的作用,因为离栈顶越近,理论上越有可能被覆盖做它用,但是编译时已经把局部变量的空间大小考虑好了,所以似乎也不会出现别的局部变量占用的情况。。。。。。
另外还可以看到 C数组虽然没有被初始化为0,但是编译器最后还是将剩余的15h个字节的数组空间填0了。
。。。。。。 其实可以作为对比,再来几个,对照着分析一下,就能确定了。我是不弄啦,头晕。不过对于这段代码,虽然没有确定的看出大括号的作用,但是从这中间,我学到了很多东东。很勃大 很精深。
2012-08-11 16:08
快速回复:呕心沥血两小时 终于弄的差不多了
数据加载中...
 
   



关于我们 | 广告合作 | 编程中国 | 清除Cookies | TOP | 手机版

编程中国 版权所有,并保留所有权利。
Powered by Discuz, Processed in 0.048319 second(s), 8 queries.
Copyright©2004-2025, BC-CN.NET, All Rights Reserved