免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 705 | 回复: 0
打印 上一主题 下一主题

[复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2007-02-15 16:44 |只看该作者 |倒序浏览
我们先看看一个小程序,再看看它对应的汇编代码,一切都清楚了。
#include

int main(int argc, char* argv[])
{
    int  n = 0;
    int* p = alloca(1024);

    printf("&n=%p p=%p\n", &n, p);
    return 0;
}

汇编代码为:
int main(int argc, char* argv[])
{
8048394:       55                      push   %ebp
8048395:       89 e5                   mov    %esp,%ebp
8048397:       83 ec 18                sub    $0x18,%esp
804839a:       83 e4 f0                and    $0xfffffff0,%esp
804839d:       b8 00 00 00 00          mov    $0x0,%eax
80483a2:       83 c0 0f                add    $0xf,%eax
80483a5:       83 c0 0f                add    $0xf,%eax
80483a8:       c1 e8 04                shr    $0x4,%eax
80483ab:       c1 e0 04                shl    $0x4,%eax
80483ae:       29 c4                   sub    %eax,%esp
        int  n = 0;
80483b0:       c7 45 fc 00 00 00 00    movl   $0x0,0xfffffffc(%ebp)
        int* p = alloca(1024);
80483b7:       81 ec 10 04 00 00       sub    $0x410,%esp
80483bd:       8d 44 24 0c             lea    0xc(%esp),%eax
80483c1:       83 c0 0f                add    $0xf,%eax
80483c4:       c1 e8 04                shr    $0x4,%eax
80483c7:       c1 e0 04                shl    $0x4,%eax
80483ca:       89 45 f8                mov    %eax,0xfffffff8(%ebp)

        printf("&n=%p p=%p\n", &n, p);
80483cd:       8b 45 f8                mov    0xfffffff8(%ebp),%eax
80483d0:       89 44 24 08             mov    %eax,0x8(%esp)
80483d4:       8d 45 fc                lea    0xfffffffc(%ebp),%eax
80483d7:       89 44 24 04             mov    %eax,0x4(%esp)
80483db:       c7 04 24 98 84 04 08    movl   $0x8048498,(%esp)
80483e2:       e8 d1 fe ff ff          call   80482b8
        return 0;
80483e7:       b8 00 00 00 00          mov    $0x0,%eax
}


其中关键的一条指令为:sub    $0x410,%esp
由此可以看出实现alloca,仅仅是把ESP减去指定大小,扩大栈空间(记记住栈是向下增长),这块空间就是分配的内存。

3.         可变参数的实现。
对新手来说,可变参数的函数也是比较神奇。还是以一个小程序来说明它的实现。
#include
#include

int print(const char* fmt, ...)
{
    int n1 = 0;
    int n2 = 0;
    int n3 = 0;
    va_list ap;
    va_start(ap, fmt);

    n1 = va_arg(ap, int);
    n2 = va_arg(ap, int);
    n3 = va_arg(ap, int);

    va_end(ap);

    printf("n1=%d n2=%d n3=%d\n", n1, n2, n3);

    return 0;
}

int main(int arg, char argv[])
{
    print("%d\n", 1, 2, 3);

    return 0;
}


我们看看对应的汇编代码:
int print(const char* fmt, ...)
{
8048394:       55                      push   %ebp
8048395:       89 e5                   mov    %esp,%ebp
8048397:       83 ec 28                sub    $0x28,%esp
        int n1 = 0;
804839a:       c7 45 fc 00 00 00 00    movl   $0x0,0xfffffffc(%ebp)
        int n2 = 0;
80483a1:       c7 45 f8 00 00 00 00    movl   $0x0,0xfffffff8(%ebp)
        int n3 = 0;
80483a8:       c7 45 f4 00 00 00 00    movl   $0x0,0xfffffff4(%ebp)
        va_list ap;
        va_start(ap, fmt);
80483af:       8d 45 0c                lea    0xc(%ebp),%eax
80483b2:       89 45 f0                mov    %eax,0xfffffff0(%ebp)

        n1 = va_arg(ap, int);
80483b5:       8b 55 f0                mov    0xfffffff0(%ebp),%edx
80483b8:       8d 45 f0                lea    0xfffffff0(%ebp),%eax
80483bb:       83 00 04                addl   $0x4,(%eax)
80483be:       8b 02                   mov    (%edx),%eax
80483c0:       89 45 fc                mov    %eax,0xfffffffc(%ebp)
        n2 = va_arg(ap, int);
80483c3:       8b 55 f0                mov    0xfffffff0(%ebp),%edx
80483c6:       8d 45 f0                lea    0xfffffff0(%ebp),%eax
80483c9:       83 00 04                addl   $0x4,(%eax)
80483cc:       8b 02                   mov    (%edx),%eax
80483ce:       89 45 f8                mov    %eax,0xfffffff8(%ebp)
        n3 = va_arg(ap, int);
80483d1:       8b 55 f0                mov    0xfffffff0(%ebp),%edx
80483d4:       8d 45 f0                lea    0xfffffff0(%ebp),%eax
80483d7:       83 00 04                addl   $0x4,(%eax)
80483da:       8b 02                   mov    (%edx),%eax
80483dc:       89 45 f4                mov    %eax,0xfffffff4(%ebp)

        va_end(ap);
       printf("n1=%d n2=%d n3=%d\n", n1, n2, n3);
80483df:       8b 45 f4                mov    0xfffffff4(%ebp),%eax
80483e2:       89 44 24 0c             mov    %eax,0xc(%esp)
80483e6:       8b 45 f8                mov    0xfffffff8(%ebp),%eax
80483e9:       89 44 24 08             mov    %eax,0x8(%esp)
80483ed:       8b 45 fc                mov    0xfffffffc(%ebp),%eax
80483f0:       89 44 24 04             mov    %eax,0x4(%esp)
80483f4:       c7 04 24 f8 84 04 08    movl   $0x80484f8,(%esp)
80483fb:       e8 b8 fe ff ff          call   80482b8

        return 0;
8048400:       b8 00 00 00 00          mov    $0x0,%eax
}
int main(int arg, char argv[])
{
8048407:       55                      push   %ebp
8048408:       89 e5                   mov    %esp,%ebp
804840a:       83 ec 18                sub    $0x18,%esp
804840d:       83 e4 f0                and    $0xfffffff0,%esp
8048410:       b8 00 00 00 00          mov    $0x0,%eax
8048415:       83 c0 0f                add    $0xf,%eax
8048418:       83 c0 0f                add    $0xf,%eax
804841b:       c1 e8 04                shr    $0x4,%eax
804841e:       c1 e0 04                shl    $0x4,%eax
8048421:       29 c4                   sub    %eax,%esp
        int n = print("%d\n", 1, 2, 3);
8048423:       c7 44 24 0c 03 00 00    movl   $0x3,0xc(%esp)
804842a:       00
804842b:       c7 44 24 08 02 00 00    movl   $0x2,0x8(%esp)
8048432:       00
8048433:       c7 44 24 04 01 00 00    movl   $0x1,0x4(%esp)
804843a:       00
804843b:       c7 04 24 0b 85 04 08    movl   $0x804850b,(%esp)
8048442:       e8 4d ff ff ff          call   8048394
8048447:       89 45 fc                mov    %eax,0xfffffffc(%ebp)

        return 0;
804844a:       b8 00 00 00 00          mov    $0x0,%eax
}


从汇编代码中,我们可以看出,参数是逆序入栈的。在取参数时,先让ap指向第一个参数,又因为栈是向下增长的,不断把指针向上移动就可以取出所有参数了。

l         堆
在内存分配算法一节中再详细讲解。


本文来自ChinaUnix博客,如果查看原文请点:http://blog.chinaunix.net/u/30686/showart_247775.html
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP