免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
楼主: ethantsien
打印 上一主题 下一主题

[C] 一道题 --- 学C就要关注更底层的东西 [复制链接]

论坛徽章:
0
31 [报告]
发表于 2012-10-15 14:41 |只看该作者
testq    %rax, %rax
cmovne   (%rax), %eax

如果%rax里存的是空指针,即使cmovne判断是假,但后面的引用照样会进行,事实就是这样。

论坛徽章:
11
未羊
日期:2013-12-16 12:45:4615-16赛季CBA联赛之青岛
日期:2016-04-11 19:17:4715-16赛季CBA联赛之广夏
日期:2016-04-06 16:34:012015亚冠之卡尔希纳萨夫
日期:2015-11-10 10:04:522015亚冠之大阪钢巴
日期:2015-07-30 18:29:402015亚冠之城南
日期:2015-06-15 17:56:392015亚冠之卡尔希纳萨夫
日期:2015-05-15 15:19:272015亚冠之山东鲁能
日期:2015-05-14 12:38:13金牛座
日期:2014-12-04 15:34:06子鼠
日期:2014-10-16 13:40:4715-16赛季CBA联赛之八一
日期:2016-07-22 09:41:40
32 [报告]
发表于 2012-10-15 14:42 |只看该作者
本帖最后由 zylthinking 于 2012-10-15 14:50 编辑
ethantsien 发表于 2012-10-15 14:31
你以为我没跑程序?你这不是在说自己吗?


好吧, 是我没跑程序, 手上没有 gcc 4.6 无法验证; 如果是真的它产生出的代码, 那你赢了, 但很显然, 这是 gcc 的bug

论坛徽章:
59
2015年亚洲杯之约旦
日期:2015-01-27 21:27:392015年亚洲杯之日本
日期:2015-02-06 22:09:41拜羊年徽章
日期:2015-03-03 16:15:432015年辞旧岁徽章
日期:2015-03-03 16:54:152015年迎新春徽章
日期:2015-03-04 09:50:282015元宵节徽章
日期:2015-03-06 15:50:392015年亚洲杯之阿联酋
日期:2015-03-19 17:39:302015年亚洲杯之中国
日期:2015-03-23 18:52:23巳蛇
日期:2014-12-14 22:44:03双子座
日期:2014-12-10 21:39:16处女座
日期:2014-12-02 08:03:17天蝎座
日期:2014-07-21 19:08:47
33 [报告]
发表于 2012-10-15 14:44 |只看该作者
回复 31# ethantsien


    不对啊,cmovene ,不是要先判断 z-flag是否为0 再mov么?

论坛徽章:
2
青铜圣斗士
日期:2015-11-26 06:15:59数据库技术版块每日发帖之星
日期:2016-07-24 06:20:00
34 [报告]
发表于 2012-10-15 14:47 |只看该作者
来晚了啊!神帖留名!!!

ethantsien 发表于 2012-10-15 13:06
就像讨论溢出是一个道理,溢出的代码,编译期间也不会报错,运行时才会有BUG。

这段代码在运行时,是会有BUG的,如果不学习编译器的工作方式,汇编指令和CPU体系结构的话,很容易写出这种代码。

相信大家都觉得这是C的魅力,C吸引人的地方,需要我们对整个计算机体系结构有深入的了解。

发这道题就一个目的,C博大精深,语法问题,点一下就行,底层和算法的讨论更有意义。

不懂但厉啊!!!!!

论坛徽章:
0
35 [报告]
发表于 2012-10-15 15:06 |只看该作者
vc6:
154:  int foo(int *p)
155:  {
00401300   mov         eax,dword ptr [esp+4]
00401304   test        eax,eax
00401306   je          foo+0Bh (0040130b)
00401308   mov         eax,dword ptr [eax]
157:  }
0040130A   ret
156:    return p?*p:0;
0040130B   xor         eax,eax
157:  }

gcc:

(gdb) disas foo
Dump of assembler code for function foo:
0x08048490 <foo+0>:     push   %ebp
0x08048491 <foo+1>:     xor    %eax,%eax
0x08048493 <foo+3>:     mov    %esp,%ebp
0x08048495 <foo+5>:     mov    0x8(%ebp),%edx
0x08048498 <foo+8>:     test   %edx,%edx
0x0804849a <foo+10>:    je     0x804849e <foo+14>
0x0804849c <foo+12>:    mov    (%edx),%eax
0x0804849e <foo+14>:    pop    %ebp
0x0804849f <foo+15>:    ret   
End of assembler dump.

论坛徽章:
0
36 [报告]
发表于 2012-10-15 15:21 |只看该作者
测试程序:

  1. #include "stdio.h"

  2. int foo(int *p)
  3. {
  4.     return(p? *p: 0);
  5. }

  6. int main(void)
  7. {
  8.     int i = 10;
  9.     int b;

  10.     b = foo(&i);
  11.     printf("b = %d\n",b);

  12.     b = foo(0);
  13.     printf("b = %d\n",b);

  14.     return 1;

  15. }
复制代码
gcc -O3的汇编

  1. foo:
  2. .LFB22:
  3.         .cfi_startproc
  4.         movl        4(%esp), %edx
  5.         xorl        %eax, %eax
  6.         testl        %edx, %edx
  7.         je        .L2
  8.         movl        (%edx), %eax
  9. .L2:
  10.         rep
  11.         ret
复制代码
执行结果:
kimi@ubuntu:~$ gcc -O3 -o test test.c
kimi@ubuntu:~$ ./test
b = 10
b = 0

gcc -O2的汇编
  1.        
  2. foo:
  3. .LFB22:
  4.         .cfi_startproc
  5.         movl        4(%esp), %edx
  6.         xorl        %eax, %eax
  7.         testl        %edx, %edx
  8.         je        .L2
  9.         movl        (%edx), %eax
  10. .L2:
  11.         rep
  12.         ret
复制代码
执行结果
kimi@ubuntu:~$ gcc -O2 -o test test.c
kimi@ubuntu:~$ ./test
b = 10
b = 0

gcc -O1的汇编

  1. foo:
  2. .LFB22:
  3.         .cfi_startproc
  4.         movl        4(%esp), %edx
  5.         movl        $0, %eax
  6.         testl        %edx, %edx
  7.         je        .L2
  8.         movl        (%edx), %eax
  9. .L2:
  10.         rep
  11.         ret
复制代码
执行结果:
kimi@ubuntu:~$ gcc -O1 -o test test.c
kimi@ubuntu:~$ ./test
b = 10
b = 0

说真的,三种优化选项都用了,真没看出有什么bug.
testl都是先跳转,后引用!!
gcc 版本4.6



论坛徽章:
0
37 [报告]
发表于 2012-10-15 16:06 |只看该作者
今天比较闲,哈哈。再编个64位的 gcc version 4.1.2

gcc -m64 -O2 tt.c

int foo(int *p)
{
  return p?*p:0;
}

int main(int argc, char** argv)
{
  int *p=malloc(100);
  *p=1;
  *(p+1)=2;
  int i = foo(p);
  return i;
}


Breakpoint 1, 0x00000000004004b0 in main ()
(gdb) disas
Dump of assembler code for function main:
0x00000000004004b0 <main+0>:    sub    $0x8,%rsp
0x00000000004004b4 <main+4>:    mov    $0x64,%edi
0x00000000004004b9 <main+9>:    callq  0x400398 <malloc@plt>
0x00000000004004be <main+14>:   movl   $0x1,(%rax)
0x00000000004004c4 <main+20>:   movl   $0x2,0x4(%rax)
0x00000000004004cb <main+27>:   mov    %rax,%rdi
0x00000000004004ce <main+30>:   add    $0x8,%rsp
0x00000000004004d2 <main+34>:   jmpq   0x4004a0 <foo>
End of assembler dump.
(gdb) disas foo
Dump of assembler code for function foo:
0x00000000004004a0 <foo+0>:     xor    %eax,%eax
0x00000000004004a2 <foo+2>:     test   %rdi,%rdi
0x00000000004004a5 <foo+5>:     je     0x4004a9 <foo+9>
0x00000000004004a7 <foo+7>:     mov    (%rdi),%eax
0x00000000004004a9 <foo+9>:     repz retq
End of assembler dump.

论坛徽章:
1
摩羯座
日期:2013-12-19 10:04:07
38 [报告]
发表于 2012-10-15 17:57 |只看该作者
有一个疑问
这里的
p?*p:0
的运行
会不会涉及 NULL 的实现??

论坛徽章:
2
亥猪
日期:2014-03-19 16:36:35午马
日期:2014-11-23 23:48:46
39 [报告]
发表于 2012-10-15 18:07 |只看该作者
回楼上和楼主:

某些时候思考多了,不如不思考。

论坛徽章:
0
40 [报告]
发表于 2012-10-15 19:06 |只看该作者
真没看出**BUG, 楼主最好用实际例子论证下
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

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

清除 Cookies - ChinaUnix - Archiver - WAP - TOP