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