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
НТН