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
C 编译器';s声称的while循环优化_C_Performance_Assembly_While Loop - Fatal编程技术网

C 编译器';s声称的while循环优化

C 编译器';s声称的while循环优化,c,performance,assembly,while-loop,C,Performance,Assembly,While Loop,在嵌入式编程讲座的一节中,Samek博士解释了编译器是如何在“原始代码”上实现效率的(大概是指由语法逻辑顺序决定的实现): 我希望你已经注意到了 反汇编代码实现了不同于的控制流 我为while循环描述的内容。原来的代码应该是 首先测试条件,然后跳过环体,如果 情况并非如此。编译后的代码以无条件 分支并反转循环体的顺序和 条件然而,当你仔细想想,这两种控制流 是等效的,除了生成的一个更快,因为它只有 循环底部的一个条件分支 在整个解释过程中,他参考了所示的两个流程图。描述编译代码的图表说明了“它在

在嵌入式编程讲座的一节中,Samek博士解释了编译器是如何在“原始代码”上实现效率的(大概是指由语法逻辑顺序决定的实现):

我希望你已经注意到了 反汇编代码实现了不同于的控制流 我为while循环描述的内容。原来的代码应该是 首先测试条件,然后跳过环体,如果 情况并非如此。编译后的代码以无条件 分支并反转循环体的顺序和 条件然而,当你仔细想想,这两种控制流 是等效的,除了生成的一个更快,因为它只有 循环底部的一个条件分支

在整个解释过程中,他参考了所示的两个流程图。描述编译代码的图表说明了“它在循环的底部只有一个条件分支”。我似乎看不出这在实践中是如何工作的:

  • 这是我拍摄的一个屏幕截图,显示了如何实现原始代码。(初始)机器指令的顺序:
0x2815 CMP
->
0x1c40添加
->
重复,直到条件为false

  • 是另一个屏幕截图,显示编译器使用的序列。(初始)机器指令的顺序:
0x2815 CMP
->
0xdbfc BLT.N
->
0x1c40添加
->
重复,直到条件为false

我可以理解这两个控制流是如何等价的(至少从图表本身来看是如此),但肯定不能理解生成的控制流(右侧)是如何更快的。首先,两个图开头的箭头指向相同的分支。第二,尽管分支在右侧示意图的后面出现,正如您从屏幕截图中看到的,模拟器似乎显示这两种方法都是从与比较相关的机器指令开始的(
0x2815 CMP


如何使流程图与我在实践中看到的内容相一致?

唯一重要的说明是在每个循环中重复的说明。逻辑重新排列的要点是,每一轮循环只有一次跳跃。在整个循环前后可能会有几次跳跃,但我们不关心这些。唯一昂贵的事情是那些反复做的事情。

唯一重要的指令是那些在每一轮循环中重复的指令。逻辑重新排列的要点是,每一轮循环只有一次跳跃。在整个循环前后可能会有几次跳跃,但我们不关心这些。唯一昂贵的事情是那些反复做的事情。

我同意Kerren SB的回答。我将更详细地讨论它:

原始逻辑具有在每次迭代期间执行的以下跳转指令:

begin_loop:
    cmp counter, 21
    jge end_loop           ; jump when greater or equal
    ...
    jmp begin_loop
end_loop:
    ....
    jmp test_loop          ; executed once; not part of loop
begin_loop:
    ...
test_loop:
    cmp counter, 21
    jlt begin_loop         ; jump when less than
    ...
修改后的逻辑在每次迭代中执行一条指令:

begin_loop:
    cmp counter, 21
    jge end_loop           ; jump when greater or equal
    ...
    jmp begin_loop
end_loop:
    ....
    jmp test_loop          ; executed once; not part of loop
begin_loop:
    ...
test_loop:
    cmp counter, 21
    jlt begin_loop         ; jump when less than
    ...

因此在循环中,无条件的
jmp begin\u循环被保存。

我同意Kerren SB的答案。我将更详细地讨论它:

原始逻辑具有在每次迭代期间执行的以下跳转指令:

begin_loop:
    cmp counter, 21
    jge end_loop           ; jump when greater or equal
    ...
    jmp begin_loop
end_loop:
    ....
    jmp test_loop          ; executed once; not part of loop
begin_loop:
    ...
test_loop:
    cmp counter, 21
    jlt begin_loop         ; jump when less than
    ...
修改后的逻辑在每次迭代中执行一条指令:

begin_loop:
    cmp counter, 21
    jge end_loop           ; jump when greater or equal
    ...
    jmp begin_loop
end_loop:
    ....
    jmp test_loop          ; executed once; not part of loop
begin_loop:
    ...
test_loop:
    cmp counter, 21
    jlt begin_loop         ; jump when less than
    ...

因此,在循环中,无条件的
jmp begin\u循环
被保存。

我不知道您的屏幕截图是否有任何不同。我看不出有什么不同。我无法通过
diff
传送视频。请尽可能使用文本。我在屏幕的两个封口之间切换。代码是相同的,只是在不同的点暂停。令人恼火的是,整个窗口都有一点偏移,所以在它们之间切换时,所有的东西都会移动一小部分。@PeterCordes两个屏幕封顶中的代码实际上是完全相同的。为什么会有什么不同呢?我的问题完全与编译器如何能够在机器级别更有效地执行while循环有关。差别仅仅在于机器指令的两个序列之间,这可以通过观察中间的“拆卸”窗格来观察,并比较从CMP开始的while循环的机器指令。(我已经用文本编写了这两套说明-见上文)。我的意思是反汇编是一样的。很抱歉,在我编辑完我的评论时,这还不清楚。@n.m.屏幕截图(以及其中的差异)在文本中有明确的描述。我提供了屏幕截图,这样我提供的机器指令就可以作为给定的,而不必观看我链接的整个视频。请记住,在我问题的原始版本中,我强调了一个事实,即我是机器级编程的初学者。我不知道您的屏幕截图是否有任何不同。我看不出有什么不同。我无法通过
diff
传送视频。请尽可能使用文本。我在屏幕的两个封口之间切换。代码是相同的,只是在不同的点暂停。令人恼火的是,整个窗口都有一点偏移,所以在它们之间切换时,所有的东西都会移动一小部分。@PeterCordes两个屏幕封顶中的代码实际上是完全相同的。为什么会有什么不同呢?我的问题完全与编译器如何能够在机器级别更有效地执行while循环有关。差别仅仅在于机器指令的两个序列之间,这可以通过观察中间的“拆卸”窗格来观察,并比较从CMP开始的while循环的机器指令。(