Циклы на assembler

Я пытался написать код, задача которого звучит так: найти сумму чисел натурального ряда от 1 до N, которые без остатка делятся на 3. Я знаю, что задача предельно простая. На C++ она выполняется без проблем, но вот assembler вызывает проблемы. Привожу в пример код, который я сделал (работает неправильно):

__asm
{
    mov ecx, n
    mov eax, 0
    mov ebx, 0
    mov esi, 0
    asm_for:
    add ebx, 1
        add eax, 1
        mov edx, 0
        div b
        cmp edx, 0
        JE then
        JNE then2
        then: add a, ebx
        then2: add esi, 1
        Loop asm_for
        mov edi, a
        mov sum, edi
}

cout << sum << endl;

Другими словами, как я вижу этот код (начиная со строки "cmp edx, 0"): если условие "cmp edx, 0" ВЫПОЛНЯЕТСЯ, то тогда выполняется действие then, а за ним команда Loop. Если условие "cmp edx, 0" НЕ ВЫПОЛНЯЕТСЯ, то тогда выолняется действие then2, а за ним команда Loop.

P.S.

esi я добавил только для того, чтобы было что выполнять в then2. Никакой роли это здесь не играет.

Скажите, пожалуйста, в чем моя ошибка. И да, советы по ссылке ниже мне не помогли.

https://stackoverflow.com/questions/42188685/implementing-a-flow-1-if-else-if-2-in-assembly


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

Автор решения: Кирилл Малышев

Команда DIV делит число, записанное в регистрах EDX:EAX, и заполняет регистр EAX результатом, а EDX остатком от деления. Вы правильно обнуляете перед делением EDX, но не учитываете, что регистр EAX уже занят результатом деления и там нет предыдущего делимого. Делимое у вас хранится в регистре EBX. Так что замените строчку

add eax, 1

на

mov eax, ebx

Также хочется отметить, что ваш алгоритм можно оптимизировать. Необязательно проверять подряд натуральные числа на делимость на 3. На 3 делится без остатка каждое 3-е натуральное число: 3, 6, 9 и т.д. Поэтому можно сразу начинать с числа 3 и прибавлять по 3, ничего не проверяя. Можно заметить ещё, что эта последовательность является арифметической прогрессией и можно применить формулу суммы арифметической прогрессии:

введите сюда описание изображения

int result = (int) ((n / 3) / 2. * (2 * 3 + (n / 3 - 1) * 3));
→ Ссылка
Автор решения: Harry

Если задача строго звучит именно как найти сумму чисел натурального ряда от 1 до N, которые без остатка делятся на 3, то я бы делал так:

int main()
{
    unsigned int N;

    cin >> N;

    __asm {
        mov     eax, N
        mov     ecx, 3
        idiv    ecx
        mov     ecx, eax
        imul    eax, 3
        inc     ecx
        imul    eax, ecx
        shr     eax, 1
        mov     N, eax
    };

    cout << N << endl;

}
→ Ссылка