Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/70.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
gcc循环构造对汇编代码的更改_C_Gcc_Assembly_X86 - Fatal编程技术网

gcc循环构造对汇编代码的更改

gcc循环构造对汇编代码的更改,c,gcc,assembly,x86,C,Gcc,Assembly,X86,为什么gcc编译器在创建汇编代码时将while循环转换为do-while构造?我知道任何while循环都可以重写为do-while,例如在c中 while(测试){ ... } 可以重写为 if ( !test ) goto skip; do { . . . } while ( test ); skip: 通常,do while循环比while循环更有效。由于编译器希望创建一个快速(而非可读)程序,因此它将大多数while循环转换为do while循环 事实上,仅使用if和goto(近似于汇编

为什么gcc编译器在创建汇编代码时将while循环转换为do-while构造?我知道任何while循环都可以重写为do-while,例如在c中

while(测试){
...
}

可以重写为

if ( !test ) goto skip;
do {
. . .
} while ( test );
skip:

通常,
do while
循环比
while
循环更有效。由于编译器希望创建一个快速(而非可读)程序,因此它将大多数
while
循环转换为
do while
循环

事实上,仅使用
if
goto
(近似于汇编语言)实现
while
循环可以如下所示:

start:
    if ( !test ) goto skip;
    . . . // loop body
    goto start;
skip:
    ; // continue the program
这相当于
do-while
实现,但效率可能低于
do-while实现(因为后者在循环中少了一行代码):


基于anatolyg的答案,您可能想知道为什么do-while构造更有效,特别是考虑到如图所示,测试已经重复(因此生成的代码更大)。答案是,通常可以证明测试表达式在循环进入时总是正确的,所以

    if ( !test ) goto skip;
loop:
    . . . // loop body
    if ( test ) goto loop;
skip:
    . . . // continue the program
可以简化为

loop:
    . . . // loop body
    if ( test ) goto loop;
    . . . // continue program
现在,为什么不在原始转换的同时这样做,如果编译器不能证明循环至少循环一次,那么就避免原始转换呢?因为证明循环至少循环一次的算法实际上是一个通用的if条件优化器。通常的优化顺序如下所示:

  • 将所有循环转换为“规范”形式(或多或少如上面的第一个代码块所示)
  • 进行大量的优化,以期望以这种规范形式出现循环,如图所示的if语句
  • 在处理完所有与循环相关的事情之后,尝试去规范化那些可以消除冗余的地方

  • 要知道的另一件事是,有时故意保留重复的测试,因为编译器希望它产生更好的运行时行为。例如,如果编译器有理由相信循环通常循环多次,但不能证明它总是至少循环一次,那么循环上方的条件分支指令几乎总是失败,而循环下方的条件分支几乎总是跳转。在这种情况下,将它们分开可能会使CPU的分支预测器更加准确。分支预测精度仅次于缓存友好性,这是现代无序CPU速度的限制因素。

    因为汇编语言中没有
    for
    while
    循环。如果你想谈论汇编,编译器生成的汇编后代码。每次循环也只有一个分支(只是向后的一个)而不是两个。是的,但是如果编译器确实在循环的顶部重新组合了测试表达式,那么在循环的底部就会有一个无条件分支,这在现代CPU上几乎是免费的——它占用了一个解码单元,但从未进入主管道。非常感谢您的出色响应。
    loop:
        . . . // loop body
        if ( test ) goto loop;
        . . . // continue program