免费注册 查看新帖 |

Chinaunix

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

[C] 请问:为什么加入__volatile__还是被优化? [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2016-07-13 16:21 |只看该作者 |倒序浏览
请看:
#include <stdio.h>
int main()
{
        char input[30]={"This is a test message.\n"};
        char output[30];
        int length=25;
        __asm__ __volatile__("cld\n\t"
                "rep movsb"
                :
                :"S"(input),"D"(output),"c"(length)
                );
        printf("%s\n",output);
        return 0;
}

我是这样编译的:gcc -O asm1.c -o asm1,
可是我运行时,没有输出字符串;
如果我这样编译gcc asm1.c -o asm1
可以输出This is a test message.。
书上说加__volatile__,编译时不会被优化,
可是为什么我加了__volatile__,还是被优化,
请问为什么?怎么办?

论坛徽章:
20
程序设计版块每日发帖之星
日期:2015-08-17 06:20:00程序设计版块每日发帖之星
日期:2016-07-16 06:20:00程序设计版块每日发帖之星
日期:2016-07-18 06:20:00每日论坛发贴之星
日期:2016-07-18 06:20:00黑曼巴
日期:2016-12-26 16:00:3215-16赛季CBA联赛之江苏
日期:2017-06-26 11:05:5615-16赛季CBA联赛之上海
日期:2017-07-21 18:12:5015-16赛季CBA联赛之青岛
日期:2017-09-04 17:32:0515-16赛季CBA联赛之吉林
日期:2018-03-26 10:02:16程序设计版块每日发帖之星
日期:2016-07-15 06:20:0015-16赛季CBA联赛之江苏
日期:2016-07-07 18:37:512015亚冠之萨济拖拉机
日期:2015-08-17 12:21:08
2 [报告]
发表于 2016-07-13 20:50 |只看该作者
本帖最后由 nswcfd 于 2016-07-13 20:51 编辑

比较一下汇编,并没有被优化掉

未优化的

   0x00000000004004c4 <+0>:   push   %rbp
   0x00000000004004c5 <+1>:   mov    %rsp,%rbp
   0x00000000004004c8 <+4>:   sub    $0x50,%rsp
   0x00000000004004cc <+8>:        movl   $0x73696854,-0x30(%rbp)
   0x00000000004004d3 <+15>:        movl   $0x20736920,-0x2c(%rbp)
   0x00000000004004da <+22>:        movl   $0x65742061,-0x28(%rbp)
   0x00000000004004e1 <+29>:        movl   $0x6d207473,-0x24(%rbp)
   0x00000000004004e8 <+36>:        movl   $0x61737365,-0x20(%rbp)
   0x00000000004004ef <+43>:        movl   $0xa2e6567,-0x1c(%rbp)
   0x00000000004004f6 <+50>:        movl   $0x0,-0x18(%rbp)
   0x00000000004004fd <+57>:        movw   $0x0,-0x14(%rbp)
   0x0000000000400503 <+63>:        movl   $0x19,-0x4(%rbp)
   0x000000000040050a <+70>:        lea    -0x30(%rbp),%rax
   0x000000000040050e <+74>:        lea    -0x50(%rbp),%rdx
   0x0000000000400512 <+78>:        mov    -0x4(%rbp),%ecx
   0x0000000000400515 <+81>:        mov    %rax,%rsi
   0x0000000000400518 <+84>:        mov    %rdx,%rdi
   0x000000000040051b <+87>:        cld   
   0x000000000040051c <+88>:        rep movsb %ds%rsi),%es%rdi)
   0x000000000040051e <+90>:        lea    -0x50(%rbp),%rax
   0x0000000000400522 <+94>:        mov    %rax,%rdi

   0x0000000000400525 <+97>:        callq  0x4003b8 <puts@plt>


优化之后的

   0x00000000004004c4 <+0>:   sub    $0x48,%rsp
   0x00000000004004c8 <+4>:   movl   $0x73696854,0x20(%rsp)
   0x00000000004004d0 <+12>:  movl   $0x20736920,0x24(%rsp)
   0x00000000004004d8 <+20>:  movl   $0x65742061,0x28(%rsp)
   0x00000000004004e0 <+28>:  movl   $0x6d207473,0x2c(%rsp)
   0x00000000004004e8 <+36>:  movl   $0x61737365,0x30(%rsp)
   0x00000000004004f0 <+44>:  movl   $0xa2e6567,0x34(%rsp)
   0x00000000004004f8 <+52>:  movl   $0x0,0x38(%rsp)
   0x0000000000400500 <+60>:  movw   $0x0,0x3c(%rsp)
   0x0000000000400507 <+67>:  lea    0x20(%rsp),%rsi
   0x000000000040050c <+72>:  mov    %rsp,%rdi
   0x000000000040050f <+75>:  mov    $0x19,%ecx
   0x0000000000400514 <+80>:  cld   
   0x0000000000400515 <+81>:  rep movsb %ds%rsi),%es%rdi)
   0x0000000000400517 <+83>:  callq  0x4003b8 <puts@plt>

论坛徽章:
20
程序设计版块每日发帖之星
日期:2015-08-17 06:20:00程序设计版块每日发帖之星
日期:2016-07-16 06:20:00程序设计版块每日发帖之星
日期:2016-07-18 06:20:00每日论坛发贴之星
日期:2016-07-18 06:20:00黑曼巴
日期:2016-12-26 16:00:3215-16赛季CBA联赛之江苏
日期:2017-06-26 11:05:5615-16赛季CBA联赛之上海
日期:2017-07-21 18:12:5015-16赛季CBA联赛之青岛
日期:2017-09-04 17:32:0515-16赛季CBA联赛之吉林
日期:2018-03-26 10:02:16程序设计版块每日发帖之星
日期:2016-07-15 06:20:0015-16赛季CBA联赛之江苏
日期:2016-07-07 18:37:512015亚冠之萨济拖拉机
日期:2015-08-17 12:21:08
3 [报告]
发表于 2016-07-13 21:16 |只看该作者
rep movsb都在,只是执行完毕之后,rdi指向字符串的末尾。

未优化的场景,重新从栈上把目的地址找出来了。
而在优化的场景下,rdi原封不动的送给puts做参数了,所以打印的是outputs后面的随机内容。

论坛徽章:
20
程序设计版块每日发帖之星
日期:2015-08-17 06:20:00程序设计版块每日发帖之星
日期:2016-07-16 06:20:00程序设计版块每日发帖之星
日期:2016-07-18 06:20:00每日论坛发贴之星
日期:2016-07-18 06:20:00黑曼巴
日期:2016-12-26 16:00:3215-16赛季CBA联赛之江苏
日期:2017-06-26 11:05:5615-16赛季CBA联赛之上海
日期:2017-07-21 18:12:5015-16赛季CBA联赛之青岛
日期:2017-09-04 17:32:0515-16赛季CBA联赛之吉林
日期:2018-03-26 10:02:16程序设计版块每日发帖之星
日期:2016-07-15 06:20:0015-16赛季CBA联赛之江苏
日期:2016-07-07 18:37:512015亚冠之萨济拖拉机
日期:2015-08-17 12:21:08
4 [报告]
发表于 2016-07-13 21:50 |只看该作者
两个办法,一个引入中间寄存器,并声明rdi可变
        __asm__ __volatile__("cld\n\t"
                "mov %1,%%rdi;"
                "rep movsb"
                :
                :"S"(input),"r"(output),"c"(length)
                :"rdi");


另一个方法是使用&修饰符,但需要引入一个临时变量
        int di;
        __asm__ __volatile__("cld; rep movsb": "=&D"(di) : "S"(input), "0"(output), "c"(length));

论坛徽章:
20
程序设计版块每日发帖之星
日期:2015-08-17 06:20:00程序设计版块每日发帖之星
日期:2016-07-16 06:20:00程序设计版块每日发帖之星
日期:2016-07-18 06:20:00每日论坛发贴之星
日期:2016-07-18 06:20:00黑曼巴
日期:2016-12-26 16:00:3215-16赛季CBA联赛之江苏
日期:2017-06-26 11:05:5615-16赛季CBA联赛之上海
日期:2017-07-21 18:12:5015-16赛季CBA联赛之青岛
日期:2017-09-04 17:32:0515-16赛季CBA联赛之吉林
日期:2018-03-26 10:02:16程序设计版块每日发帖之星
日期:2016-07-15 06:20:0015-16赛季CBA联赛之江苏
日期:2016-07-07 18:37:512015亚冠之萨济拖拉机
日期:2015-08-17 12:21:08
5 [报告]
发表于 2016-07-13 21:59 |只看该作者
按照http://ibiblio.org/gferg/ldp/GCC-Inline-Assembly-HOWTO.html#s7的例子,貌似把%edi放入clobber list就可以,但貌似不行,不知道为什么?

#define mov_blk(src, dest, numwords) \
__asm__ __volatile__ (                                          \
                       "cld\n\t"                                \
                       "rep\n\t"                                \
                       "movsl"                                  \
                       :                                        \
                       : "S" (src), "D" (dest), "c" (numwords)  \
                       : "%ecx", "%esi", "%edi"                 \
                       )

论坛徽章:
20
程序设计版块每日发帖之星
日期:2015-08-17 06:20:00程序设计版块每日发帖之星
日期:2016-07-16 06:20:00程序设计版块每日发帖之星
日期:2016-07-18 06:20:00每日论坛发贴之星
日期:2016-07-18 06:20:00黑曼巴
日期:2016-12-26 16:00:3215-16赛季CBA联赛之江苏
日期:2017-06-26 11:05:5615-16赛季CBA联赛之上海
日期:2017-07-21 18:12:5015-16赛季CBA联赛之青岛
日期:2017-09-04 17:32:0515-16赛季CBA联赛之吉林
日期:2018-03-26 10:02:16程序设计版块每日发帖之星
日期:2016-07-15 06:20:0015-16赛季CBA联赛之江苏
日期:2016-07-07 18:37:512015亚冠之萨济拖拉机
日期:2015-08-17 12:21:08
6 [报告]
发表于 2016-07-14 09:49 |只看该作者
按照 https://gcc.gnu.org/onlinedocs/gcc/Extended-Asm.html 第 6.44.2.5 Input Operands 节的说法

When the compiler selects the registers to use to represent the input operands, it does not use any of the clobbered registers (see Clobbers).

那么,void test() { asm("nop"::"D"(1):"di"); } 出现如下错误也是合情合理的

<stdin>:1: error: can't find a register in class 'DIREG' while reloading 'asm'
<stdin>:1: error: 'asm' operand has impossible constraints

因为D类只有di一个寄存器,clobber又把它排除了,自然就没得选了。

不知道为什么楼上的帖子会那么用,估计是老版本的行为?

-----------------------------------------------------------------------------

PS,关于volatile的语义,上面链接的第 6.44.2.1 Volatile 节有几个很好的例子。

感觉extend asm不关心asm template里面的汇编语句是怎么写的? 完全按照input operand/output operand/clobber的约束声明来决定是否可以优化?

论坛徽章:
154
2022北京冬奥会纪念版徽章
日期:2015-08-07 17:10:5720周年集字徽章-年
日期:2022-10-26 16:44:2015-16赛季CBA联赛之深圳
日期:2022-11-02 14:02:4515-16赛季CBA联赛之八一
日期:2022-11-28 12:07:4820周年集字徽章-20	
日期:2023-07-19 08:49:4515-16赛季CBA联赛之八一
日期:2023-11-04 19:23:5115-16赛季CBA联赛之广夏
日期:2023-12-13 18:09:34
7 [报告]
发表于 2016-07-14 11:24 来自手机 |只看该作者
欢迎cpp编译大神归来
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

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

清除 Cookies - ChinaUnix - Archiver - WAP - TOP