C ++转换为汇编语言

时间:2013-11-28 03:42:59

标签: c++ assembly x86

这是我的任务。 我已经为这个程序集完成了我的代码,但有没有办法让转换速度更快? 感谢任何帮助; D

//Convert this nested for loop to assembly instructions
    for (a = 0; a < y; a++)
        for (b = 0; b < y; b++)
            for (c = 0; c < y; c++)
                if ((a + 2 * b - 8 * c) == y)
                    count++;

convert
    _asm {
                mov ecx,0
                mov ax, 0
                mov bx, 0
                mov cx, 0

                Back:
                push cx
                push bx
                push ax
                add bx, bx
                mov dx, 8
                mul dx
                add cx, bx
                sub cx, ax
                pop ax
                pop bx
                cmp cx, y
                jne increase
                inc count
                increase : pop cx
                          inc ax
                           cmp ax, y
                           jl Back

                           inc bx
                           mov ax, 0
                           cmp bx, y
                           jl Back

                           inc cx
                           mov ax, 0
                           mov bx, 0
                           cmp cx, y
                           jl Back

        }

3 个答案:

答案 0 :(得分:4)

一些通用技巧:

  1. 让循环计数器倒计时而不是向上计数。你用这种方式消除了比较。
  2. 了解LEA计算表达式的神奇之处,这些表达式包含2个特定幂的加法和缩放。在任何地方都不需要MUL
  3. 在内循环外提升循环不变的工作。 a + 2*b对于c循环的每次迭代都是常量。
  4. 使用SIDI来保存值。这应该可以帮助您避免所有pushpop指令。
  5. 如果您的值适合8位,请使用AHAL等来更有效地使用您的寄存器。
  6. 哦,mov ax, 0之后您不需要inc cx,因为AX已经为0了。

    特定于此算法:如果y为奇数,则跳过a为偶数的迭代,反之亦然。将近2倍的加速等待......(如果你想知道为什么,请用铅笔和纸做。)提示:你也不需要测试每次迭代。如果你足够聪明的话,你可以简单地逐步走2点。

    或者更好的是,制作一个封闭的表格,让您直接计算答案。 ; - )

答案 1 :(得分:3)

当你进行优化时,总是从高处开始变低,即从算法级别开始,当一切都用尽时,进入程序集转换。

首先,请注意:

8 * c = (a + 2 * b - y)

每个三联体(a,b,y)都有一个独特的c解决方案。

这是什么意思?你的3个循环可以折叠成2个。这是从运行时到y ^ 3到the y y ^ 2的巨大减少。

重写代码:

for (a = 0; a < y; a++)
    for (b = 0; b < y; b++) {
        c = (a+2*b-y);
        if (((c%8)==0) && (c >= 0)) count++;
    }

接下来观察c> = 0表示:

      a+2*b-y >= 0 
      a+2*b >= y
      a >= y-2b

请注意,两个循环可以互换,这给出了:

for (b = 0; b < y; b++) {
for (a = max(y-2*b,0); a < y; a++) {
        if (((a+2*b-y)%8)==0) count++;
} }

我们可以分成两部分:

for (b = 0; b < y/2; b++) {
for (a = y-2*b; a < y; a++) {
        if (((a+2*b-y)%8)==0) count++;
} }

for (b = y/2; b < y; b++) {
for (a = 0; a < y; a++) {
        if (((a+2*b-y)%8)==0) count++;
} }

现在我们完全取消了c。我们不能在没有提出封闭式公式(或至少部分封闭式公式)的情况下完全消除a或b,为什么?

所以这里有几个练习可以帮助你,#34;。&#34;。

  1. 我们怎样才能摆脱%8?我们现在可以消除a或b吗?
  2. 观察每个y,大约有θ^ 2个计数。为什么没有单一的封闭形式二次方(即a * y ^ 2 + b * y + c)给我们正确的计数?
  3. 给出2,怎么会想出一个封闭的公式?
  4. 现在转换为汇编语言会给你一个很大的改进:p

    (我希望所有细节都是正确的。如果你发现错误,请更正)

答案 2 :(得分:0)

Assembly Language Step-by-Step杰夫在第230页写道,

现在,速度优化在x86世界中是一个非常滑动的业务,在CPU缓存中指令而不是从内存中拉出它们是一个速度差异,它淹没了指令本身之间的大多数速度差异。其他因素在最新的Pentium级CPU中发挥作用,这些CPU几乎不可能对指令速度进行概括,并且当然不可能以任何精度进行说明。

假设您使用的是x86计算机,我的建议就是尽可能地吸收所有Math中的数学,以便为优化提供最好的答案。