ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

编译过程中遇到的问题

2021-09-11 22:01:58  阅读:142  来源: 互联网

标签:遇到 过程 编译 指令 条件 xp rdi rax


  记录一下有关编译的问题

 

  1.条件转移和条件传送

  编译器在编译条件控制的代码时,会采用两种策略进行编译。一个是条件转移(条件跳转),一个是条件传送。

  条件转移:用条件跳转指令jmp等来完成编译。类似于goto,会跳过部分代码

    movq $0,%rax
    jmp .L1                          //条件跳转指令,跳转到.L1
    movq (%rax),%rad
.L1:
    popq %rdx;

  条件传送:利用条件转移指令cmove等来完成编译,会计算条件操作的两种结果,然后根据条件来选取。可能会跳过条件转移指令后内容的改变(仍会判断,但是不满足条件则什么也不做进入下一指令)

cmpq %rsi,%rdi
cmovge %rdx,%rax          //满足rdi内容大于等于rsi,则执行move rdx,rax
ret

  两种编译方式的不同是,条件转移不按指令顺序进行编译,而条件传送则按代码顺序进行编译。

  由于现代处理器使用流水线pipelining来获得高性能,在处理上一条指令的过程中可能会同时处理下一条指令(cpu在等待上一条内容读取内存时,会先命令将下一条指令读到内存或者确定指令类型等操作)。由于条件转移在条件未判断完成时不确定下一条指令,所以会造成运行效率降低。(一般计算机会猜测判断条件来执行指令,如果猜错则会回退比较耗时)。而条件转移是顺序执行,不存在这种情况。所以条件传送效率较高。

  但是使用条件传送的条件很苛刻,如果两个表达式中任意一个可能产生错误条件或副作用就会导致非法行为,同时如果两个表达式中特别复杂需要大量工作,则编译器也不会使用这种编译方式。

  下面是错误行为的示范:

long cread(long *xp){ return xp?*xp:0);        //使用条件传送会导致错误行为,因为先计算*xp在,检验xp是否存在
//转换为汇编语言之后,更容易发现这个问题
cread:
    movq (%rdi),%rax        //直接对空指针解引用
    testq %rdi,%rdi             

  下面是副作用行为的示范:

static int x;
static int y;
int cread(){ return x>y?++x:++y;}         //使用条件转移会使两个静态变量的值都+1而不是较大的+1;

 

标签:遇到,过程,编译,指令,条件,xp,rdi,rax
来源: https://www.cnblogs.com/wildricky/p/15256890.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有