не могу понять, почему какая-то переменная изменяется - PullRequest
0 голосов
/ 18 февраля 2019

Мне было поручено создать программу, которая будет перечислять составные числа в пределах определенного пользователем диапазона.Чтобы определить, является ли число составным, я буду делить его и проверять остаток от нуля.Моя настоящая проблема заключается в попытке напечатать переменную под названием «текущий» в моем коде.current инициализируется до 3, а затем увеличивается в каждом цикле, поэтому я ожидаю, что число 4 будет напечатано первым, а 2 - первым.Как это возможно, ток даже не достигает 2, он увеличивается только с 3.

mov     ecx, terms
trial:
    inc     current
    mov     eax, current
    cdq
    mov     ebx, 2
    div     ebx
    cmp     edx, 0
    je      composite
    cmp     edx, 0
    jg      below


    composite:
        mov     edx, OFFSET current
        call    WriteDec
        call    CrLf

    below:
    loop    trial

Если я введу 9, я ожидаю, что 4, 6 и 8 будут печататься, потому что все они оставляют остаток 0 при делениина 2. вместо этого я печатаю 2, 3, 4, 5 и 6.

1 Ответ

0 голосов
/ 18 февраля 2019

WriteDec получает свой аргумент в EAX .Это печать, а не указатель (!), Который вы помещаете в EDX.WriteDec принимает целое число по значению

Когда вы звоните WriteDec в первый раз (по первому четному номеру после 3), EAX = 4/2 = 2, так что это то, что вы печатаете.Используйте отладчик для просмотра регистров, вы, вероятно, видели бы 2 в EAX.


И, кстати, ваш цикл проверяет только четные числа, а не все композиты.(И вы делаете это массово неэффективно. Даже тривиально, просто test al,1, чтобы протестировать младший бит EAX. Эта версия готова для нас перейти к циклу пробного деления послеИсключение четных чисел, но на данный момент самое простое разветвление - это просто распечатка или нет.

    mov     ecx, terms
    mov     ebx, current
trial:                  ; do {
    inc     ebx

    test     bl, 1
    jnz      odd           ; low bit set = not divisible by 2 = odd

    ;; TODO: trial division loop after ruling out even numbers
    ;; mov eax,ebx
    ;; xor edx,edx
    ;; div something  in a loop


    even:
        mov     eax, ebx    ; WriteDec takes an arg in EAX, and preserves all others
        call    WriteDec
        call    CrLf

    odd:
      cmp   ebx, ecx
      jb    trial       ; }while(current < terms)
      ;; The loop instruction is inefficient, don't bother with it
      ;; and you don't need a down-counter for the loop anyway
      ;; you already have terms

      mov    current, ebx    ; in case you care?

Самый простой способ проверить составную часть - это пробное деление: Проверка, есличисло простое в NASM Win64 Assembly .

Если вы хотите напечатать все композиты до определенного числа, было бы намного эффективнее запустить Сито Эратосфена длянайти нечетные композиты до достаточно высокого значения, затем циклически печатать каждое четное число и нечетные числа, если в решетке установлена ​​их запись растрового изображения или байтовой карты.

...