2010-05-12 1 views
1

Я хочу преобразовать цикл for в следующем коде в сборку, но я не уверен, как начать. Объяснение того, как это сделать и почему это работает, будет оценено по достоинству.используя in-line asm для записи цикла for с 2 сравнениями

Я использую VS2010, C++, записывая для x86. Код выглядит следующим образом:

for (n = 0; norm2 < 4.0 && n < N; ++n) 
{ 
    __asm{ 
    ///a*a - b*b + x 
     fld a // a 
     fmul st(0), st(0) // aa 
     fld b // b aa 
     fmul st(0), st(0) // bb aa 
     fsub // (aa-bb) // st(0) - st(1) 
     fld x // x (aa-bb) 
     fadd // (aa-bb+x) 

    /// 2.0*a*b + y; 
     fld d // d (aa-bb+x) 
     fld a // d a (aa-bb+x) 
     fmul // ad (aa-bb+x) 
     fld b // b ad (aa-bb+x) 
     fmul // abd (aa-bb+x) 
     fld y // y adb (aa-bb+x) 
     fadd // b:(adb+y) a:(aa-bb+x) 

     fld st(0) //b b:(adb+y) a:(aa-bb+x) 
     fmul st(0), st(0) // bb b:(adb+y) a:(aa-bb+x) 
     fld st(2) // a bb b:(adb+y) a:(aa-bb+x) 
     fmul st(0), st(0) // aa bb b:(adb+y) a:(aa-bb+x) 
     fadd // aa+bb b:(adb+y) a:(aa-bb+x) 
     fstp norm2 // store aa+bb to norm2, st(0) is popped. 
     fstp b 
     fstp a 
    } 
} 
+3

Вы можете попробовать обратный: переписать сборку на C++ и пусть использовать компилятор SSE2 ('/ арк: sse2'). – avakar

+0

Кажется странным; это в основном в встроенной сборке уже, и часть цикла будет не намного быстрее, чем создает компилятор C. (Во всяком случае компилятор C++, вероятно, будет генерировать более быстрый код, чем данный ассемблер) – Elemental

+0

@ Elemental Данный ассемблер уже на 20% быстрее. Во всяком случае, я пытаюсь понять это, а не оптимизировать код. – aCuria

ответ

3

Самый быстрый и простой способ, чтобы получить разбега на такого рода проблемы является первым писать код в C или C++ в качестве простой формы, как это возможно, а затем использовать ваш C/C++ для генерации asm. Затем вы можете использовать этот сгенерированный asm как шаблон для своего собственного кода asm. С помощью соответствующего компилятора, такого как gcc, вы должны использовать gcc -S. Я почти уверен, что Visual Studio похожа на ту, которая находится где-то в графическом интерфейсе (видимо, переключатель командной строки - /Fa).

0

для цикла примерно такой же, как

if norm2>=4.0 then // note condition inversed. 
    goto end; 
if 0<N then 
    goto end; 
beginloop: 

    <asm block> 

    if norm2>=4.0 then // note condition inversed. 
    goto end; 
    if (n<N) then 
    goto beginloop 
end: 
1

Я не буду писать ассемблер здесь, но три вещи, которые вы должны исследовать:

  • держать все в регистрах

  • не пересчитывайте a^2 и b^2 для a^2-b^2, если вы уже вычислили их для a^2 + b^2

  • попытаться найти условие, которое позволяет установить п на N без перебора

+0

a и b изменяются, поэтому необходимо повторно вычислить. double c = a * a - b * b + x; b = 2.0 * a * b + y; a = c; norm2 = a * a + b * b; – aCuria

+1

@aCuria, разверните цикл, и вы увидите, что a * a и b * b, используемые для вычисления norm2, используются для вычисления следующего c. – AProgrammer