免费注册 查看新帖 |

Chinaunix

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

GCC生成的指令 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2008-06-04 23:29 |只看该作者 |倒序浏览
以前工作环境是用PowerPC,很少看x86的汇编,所以对它不太熟悉。今天测试一个效率问题随便看了一下,有一些疑问:
volatile unsigned int rVal;
volatile unsigned int wVal;

void Work(void)
{
    wVal = rVal;
}

int main(int argc, char *argv[])
{
    unsigned int i;
    // unsigned int count = (2 == argc) ? atoi(argv[1]) : 10000;

    unsigned int count = 0xffffffff;
    for (i = 0; i < count; ++i)
    {
        work();
    }

    return 0;
}


编译方式(之所以用--inline-limit是因为我用的这个4.1.2缺省会把小函数展开):
gcc -O3 call_loop.c -o call_loop --inline-limit=0


编译结果:
08048360 <Work>:
8048360:       55                      push   %ebp
8048361:       a1 78 95 04 08          mov    0x8049578,%eax
8048366:       89 e5                   mov    %esp,%ebp
8048368:       5d                      pop    %ebp
8048369:       a3 74 95 04 08          mov    %eax,0x8049574
804836e:       c3                      ret
804836f:       90                      nop

08048370 <main>:
8048370:       8d 4c 24 04             lea    0x4(%esp),%ecx
8048374:       83 e4 f0                and    $0xfffffff0,%esp
8048377:       ff 71 fc                pushl  0xfffffffc(%ecx)
804837a:       55                      push   %ebp
804837b:       89 e5                   mov    %esp,%ebp
804837d:       53                      push   %ebx
804837e:       31 db                   xor    %ebx,%ebx
8048380:       51                      push   %ecx
8048381:       83 c3 01                add    $0x1,%ebx
8048384:       e8 d7 ff ff ff          call   8048360 <Work>
8048389:       83 fb ff                cmp    $0xffffffff,%ebx
804838c:       75 f3                   jne    8048381 <main+0x11>
804838e:       59                      pop    %ecx
804838f:       31 c0                   xor    %eax,%eax
8048391:       5b                      pop    %ebx
8048392:       5d                      pop    %ebp
8048393:       8d 61 fc                lea    0xfffffffc(%ecx),%esp
8048396:       c3                      ret
8048397:       90                      nop
8048398:       90                      nop
8048399:       90                      nop
804839a:       90                      nop
804839b:       90                      nop
804839c:       90                      nop
804839d:       90                      nop
804839e:       90                      nop
804839f:       90                      nop


我感到不太理解的是:
1. Work中没有任何栈变量访问,从指令操作看实在想不出把ebp压栈、修改然后再恢复有什么意义?
2. main函数中对于esp的只在为什么要先加上一个4压到栈里面,然后恢复到ecx再减去个4?

另外用gdb调试时如果直接用b main则断点并不是加在函数入口的第一条指令上,而是0x804837e上。

试过用-O3编译,没什么区别。

[ 本帖最后由 Cyberman.Wu 于 2008-6-5 09:00 编辑 ]

论坛徽章:
0
2 [报告]
发表于 2008-06-05 01:53 |只看该作者
原帖由 Cyberman.Wu 于 2008-6-4 23:29 发表 [url=http://bbs.chinaunix.net/redirect.php?goto=findpost&pid=我感到不太理解的是:
1. Work中没有任何栈变量访问,从指令操作看实在想不出把ebp压栈、修改然后再恢复有什么意义?
2. main函数中对于esp的只在为什么要先加上一个4压到栈里面,然后恢复到ecx再减去个4?

另外用gdb调试时如果直接用b main则断点并不是加在函数入口的第一条指令上,而是0x804837e上。

试过用-O3编译,没什么区别 ...



  编译器就是按照固定的方式给出代码,这很正常嘛。你又不给它发出不需要 frame pointer 的命令。这你也怨编译器

-fomit-frame-pointer 选项去掉 stack frame
-finline-functions 选项由编译器去决定是否 inline

论坛徽章:
0
3 [报告]
发表于 2008-06-05 10:22 |只看该作者
这个应该是CPU的ABI定义好的结构,所有函数都应该遵守。
即使堆栈没有任何变量,在正常的时候用不到,但是程序异常,需要查看调用栈的时候,就用到了。

论坛徽章:
0
4 [报告]
发表于 2008-06-05 14:07 |只看该作者
原帖由 mik 于 2008-6-5 01:53 发表



  编译器就是按照固定的方式给出代码,这很正常嘛。你又不给它发出不需要 frame pointer 的命令。这你也怨编译器

-fomit-frame-pointer 选项去掉 stack frame
-finline-functions 选项由编译器 ...



我不是怨编译器。以前我用的也是GCC,不过是针对嵌入式的交叉编译器,根本不需要任何选项,只要优化了对于这种“叶子函数”就不会再生成调整栈的指令了,因为没有任何意义。

论坛徽章:
0
5 [报告]
发表于 2008-06-05 14:10 |只看该作者
原帖由 SuperZ 于 2008-6-5 10:22 发表
这个应该是CPU的ABI定义好的结构,所有函数都应该遵守。
即使堆栈没有任何变量,在正常的时候用不到,但是程序异常,需要查看调用栈的时候,就用到了。


x86和我以前用的PowerPC确实不一样,它只要call一个函数就一定会自动调整一下栈,但在上面增加一个栈里面没有任何数据的时候异常了多一层无用的栈并不会有太大帮助吧。
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

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

清除 Cookies - ChinaUnix - Archiver - WAP - TOP