Easy68k, реализуя этот цикл

int X = 0;
int Y = 1;
while(X <= 10 ){
    if(X%2 == 0)
        Y = Y * X;
    else 
        Y++;

    X++;
}
cout << "Y is: " << Y;

Это то, что у меня есть для моего кода Easy68k.

ORG    $1000
START:                  ; first instruction of program

MOVE.W  #0,D1           ;PUT 0 IN D1 (X)
MOVE.W  #1,D2           ;PUT 1 IN D2 (Y)

LOOP CLR.W   D3        ;Find the remainder
     MOVE.W  D1,D3
     DIVU    #2,D3
     SWAP    D3

     CMP     #0,D3      ;Compare remainder with 0
     BEQ     EQUAL      ;If equal, then go to equal

     ADD.W   #1,D2      ;Y++
     ADD.W   #1,D1      ;X++

     CMP     #11,D1     ;Compare D1 with 11
     BEQ     DONE       ;If D1 equals 11, break loop.      
     BRA     LOOP


EQUAL MULU.W  D1,D2     ;Multiply D1 and D2 and store it in D2
      ADD.W   #1,D1     ;X++
      CMP     #11,D1    ;Compare D1 with 11
      BEQ     DONE      ;If D1 equals 11, break loop. 
      BRA     LOOP


DONE LEA MESSAGE,A1
     MOVE.W #14,D0
     TRAP #15

     MOVE.W  D2,D1

     MOVE.W #3,D0
     TRAP #15


    SIMHALT             ; halt simulator

MESSAGE DC.W    'Y is: ',0


    END    START        ; last line of source

Я не совсем уверен, что неправильно в моем коде, но я чувствую, что это проблема в начале раздела цикла. Я следовал вместе с кодом, но я все еще не могу понять, где он идет не так. Когда я запускаю его, он выдает Y: 10. D1 и D2 также оба A или 10. Любая помощь приветствуется.

3 ответа

Решение

После выполнения деления и обмена у вас все еще есть результат и остаток от деления в d3, Это означает, что он никогда не будет нулевым, а сравнение всегда ложным. Вам нужно обнулить верхнюю часть and или используйте форму cmp который использует только нижнюю часть.

Просто примечание: когда вы делаете остатки степеней двух, вы также можете пропустить деление и использовать and непосредственно со значением минус один. В этом случае остаток от деления на два такой же, как and со значением 1.

Отвечая на вопрос "что не так":

LOOP CLR.W   D3        ;Find the remainder
     MOVE.W  D1,D3
     DIVU    #2,D3

divu.w а также divs.w Команды на 68000 получают полное 32-битное слово из второго аргумента и делят его на 16-битное слово, указанное в первом аргументе. Ваш код не удосуживается очистить старшие 16 бит d3 до деления. Таким образом, изменение очевидно:

LOOP CLR.L   D3        ;Find the remainder
     ;all the same from here on

Вместо того, чтобы использовать divu более эффективный и быстрый механизм, чтобы сделать то же самое, что и x%2, - просто проверить состояние бита 0. Это также даст немного меньше кода. Это, очевидно, работает только для мода 2, и любые другие значения потребуют другого подхода (возможно, даже страшный разрыв:))

Изменение существующего кода для чтения (обрезано для краткости):

LOOP CLR.W   D3        ;Find the remainder
     MOVE.W  D1,D3
     btst    #0,d3     ; Test bit 0
     BEQ     EQUAL      ;If equal, then go to equal
     ...

Будет выполняться значительно быстрее (на реальном оборудовании).. не то, что вы, вероятно, заметите:)

Это работает, потому что мод 2 по сути говорит вам, является ли число четным или нечетным, что можно сделать очень дешево, просто посмотрев, установлен ли бит 0

НТН

Другие вопросы по тегам