c# - 为什么.NET Native 以相反的顺序编译循环?

标签 c# assembly x86 micro-optimization .net-native

我正在研究由 .NET Native 编译器执行的优化技术。 我创建了一个示例循环:

        for (int i = 0; i < 100; i++)
        {
            Function();
        }

我用 Native 编译了它。然后我在 IDA 中反汇编了包含机器代码的结果 .dll 文件。结果,我有:

IDA output

(我去掉了一些不需要的行,所以不用担心地址行不一致)

我理解 add esi, 0FFFFFFFFh 的意思实际上是从 esi 中减去 1 并在需要时更改零标志,因此如果没有零,我们可以跳到开头达到了。

我不明白的是编译器为什么要反转循环?

我得出的结论是

LOOP:
add esi, 0FFFFFFFFh
jnz LOOP

只是比例如更快

LOOP:
inc esi
cmp esi, 064h
jl LOOP

但这真的是因为这个吗?速度差异真的很大吗?

最佳答案

inc might be slower than add because of the partial flag update .此外,add 会影响零标志,因此您无需使用其他 cmp 指令。直接跳就行了。

这是一个著名的类型 loop optimization

reversal: Loop reversal reverses the order in which values are assigned to the index variable. This is a subtle optimization which can help eliminate dependencies and thus enable other optimizations. Also, certain architectures utilize looping constructs at Assembly language level that count in a single direction only (e.g. decrement-jump-if-not-zero (DJNZ)).

您可以看到其他编译器的结果here .

关于c# - 为什么.NET Native 以相反的顺序编译循环?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36430287/

相关文章:

c# - 空值的处理

assembly - 将 64 位整数加载到 double SSE2 寄存器的最佳方法?

linux - 如何用汇编语言(linux)写入/读取并行端口?

assembly - x86 函数必须保留哪些寄存器?

c# - 获取数组中最大和最小的数

c# - 如何使用 C# 在 word 中使用打印到文件选项创建 postscript 文件?

installation - WiX DisableRegistryReflection ="yes"属性不起作用

assembly - 为什么我的堆栈指针仅以16的倍数递增?

c# - 如何修改 XElement 的内容?

assembly - NASM 中的 "push BYTE 0x80"和 "warning: signed byte value exceeds bounds"