Как посчитать легкий пример?

Не получается посчитать пример Определить номер (n) элемента последовательности an = 3* n^2 – 5 * n + 12, при котором сумма элементов последовательности превысит 1500 По идее в конце N должна быть = 12. Код неправильно работает, я думаю из-за возведения в степень. Прошу помощи


    int main()          // начало программы на языке С++
{
    long    N = 0;      // ячейка памяти для аргумента
    long    S = 0;      // ячейка для хранения суммы
    long    P = 1;      // ячейка для накопления 8n 
    long kv = 2;
    long tri = 3;

    _asm
    {; начало ассемблерной вставки
        m1 : inc    N;// увеличение аргумента
        //mov   EBX, 3;// EBX = 3
        mov EAX, P;// ECX = n(1)
        mul kv;
        mul tri; 
        mov P, EAX; // 3*n^2 in P
        add S, EAX;// накопление суммы
        
        mov EAX, 5;// EAX = 5
        mul N;// EAX = 5 * n
        sub S, EAX;// накопление суммы

        mov EAX, N;// EAX = n
        add EAX, 12;
        add S, EAX;

        cmp S, 1500;// сравнение суммы с 1500
        jc  m1;// переход, если сумма меньше 1500
    }
}

Ответы (2 шт):

Автор решения: Zhihar
int res = 0;

__asm {

    mov ecx, 0      ; счётчик n 
    mov edx, 0      ; счётчик суммы

    calc_loop:
    
    mov eax, ecx    ; вычисляем 5n
    mov esi, 5
    mul esi
    mov ebx, eax

    mov eax, ecx    ; вычисляем 3n^2
    mul ecx
    mov esi, 3
    mul esi

    sub eax, ebx    ; вычисляем 3n^2 - 5n + 12
    add eax, 12

    add edx, eax    ; увеличиваем сумму

    inc ecx         ; увеличиваем n

    cmp edx, 1200   ; если сумма менее 1200 выполняем этап вычислений еще раз
    jl calc_loop

    mov res, ecx
}

std::cout << res << std::endl;

так?

→ Ссылка
Автор решения: vp_arth

Член последовательности, для простоты, можно представить как (3n-5)*n + 12

Решение для суммы ряда:

asm (
    "xor ebx, ebx;"           // sum = 0;
    "xor ecx, ecx;"           // n = 0;
    "it:"                     // do {
    "lea eax, [ecx+ecx*2];"   //   an = (3*n
    "sub eax, 5;"             //             - 5)
    "mul ecx;"                //                  * n
    "add eax, 12;"            //                      + 12;

    "add ebx, eax;"           //   sum += an;

    "cmp ebx, 1500;"          //   if (sum > 1500)
    "jg res;"                 //     break;
    "inc ecx;"                //   ++n;

    "jmp it;"                 // } while (true);
    "res:mov %0, ecx;"

    : "=r" (dst) // 12
);

Решение от компилятора.


Ниже решение не той задачи. Ищет член превышающий 1500 :(

// g++ -masm=intel tmp.cpp -o /tmp/tmp && /tmp/tmp
#include <cstdio>

int main()
{
    int dst;
    // an = 3* n^2 – 5 * n + 12, an > 1500
    // (3n-5)*n + 12
    asm (
        "xor ecx, ecx;"
        "it:"                   // do {
        "lea eax, [ecx+ecx*2];" // an =(3*n
        "sub eax, 5;"           //         -5)
        "mul ecx;"              //            *n
        "add eax, 12;"          //              +12;

        "cmp eax, 1500;"        // if (an > 1500)
        "jg res;"               //     break;
        "inc ecx;"              // ++n;
        "jmp it;"               // } while (True);

        "res: mov %0, ecx;"

        : "=r" (dst)
    );

    printf("%d\n", dst); // 24
}

Посмотрел, что GCC генерирует на код выше в комментариях, что-то вроде:

asm (
    "mov DWORD PTR [rbp-8], 0;"
    "mov DWORD PTR [rbp-4], 0;"

    ".L_1: mov edx, DWORD PTR [rbp-4];" 
    "mov eax, edx;"                     
    "add eax, eax;"                     
    "add eax, edx;"                     
    "sub eax, 5;"
    "imul eax, DWORD PTR [rbp-4];"
    "add eax, 12;"
    "mov DWORD PTR [rbp-8], eax;"
    "cmp DWORD PTR [rbp-8], 1500;"
    "jg .L_2;"
    "add DWORD PTR [rbp-4], 1;"
    "jmp .L_1;"
    ".L_2: mov %0, DWORD PTR [rbp-4];"

    : "=r" (dst)
);

я на 3 умножаю интереснее))

→ Ссылка