@nazariy228

Где ошибка в коде?

uint16_t program[] = {
/* Ввод числа */
/*mem[0x3000]=*/ 0xF020, // TRAP x20 ; Считать символ с клавиатуры в R0
/*mem[0x3001]=*/ 0xF021, // TRAP x21 ; Эхо символа на консоль (опционально)
/*mem[0x3002]=*/ 0x5020, // AND R0, R0, #0x0F ; Конвертировать ASCII в число
/*mem[0x3003]=*/ 0x5000, // AND R1, R1, #0 ; Очистить R1 для введённого числа
/*mem[0x3004]=*/ 0x1020, // ADD R1, R0, #0 ; Скопировать введённое число в R1

/* Инициализация делителя в R2 и флага простоты в R4 */
/*mem[0x3005]=*/ 0x5060, // AND R2, R2, #0 ; Очистить R2 для делителя
/*mem[0x3006]=*/ 0x1022, // ADD R2, R2, #2 ; Установить R2 = 2 (начальный делитель)
/*mem[0x3007]=*/ 0x5460, // AND R4, R4, #0 ; Очистить R4 для флага простоты
/*mem[0x3008]=*/ 0x1461, // ADD R4, R4, #1 ; Установить R4 = 1 (считаем простым до доказательства обратного)

/* Проверка: если R1 < 2, то число не простое */
/*mem[0x3009]=*/ 0x1021, // ADD R1, R1, #-1 ; Проверить, если R1 < 2
/*mem[0x300A]=*/ 0x0E06, // BRn NOT_PRIME ; Если R1 < 2, перейти к NOT_PRIME
/*mem[0x300B]=*/ 0x1020, // ADD R1, R1, #1 ; Восстановить R1 (R1 >= 2)

/* Начало цикла проверки простоты */
/*mem[0x300C]=*/ 0x5280, // ADD R3, R2, #0 ; Скопировать R2 в R3 (текущий делитель)
/*mem[0x300D]=*/ 0x5400, // AND R4, R4, #1 ; Установить R4 = 1 (предполагаем, что число простое)

/*mem[0x300E]=*/ 0x9463, // NOT R3, R3 ; Задать R3 = -R2 (для вычитания)
/*mem[0x300F]=*/ 0x1C83, // ADD R4, R4, R3 ; Вычесть R2 из R4 (проверить делимость)
/*mem[0x3010]=*/ 0x1022, // ADD R4, R4, R2 ; Если остаток 0, значит число не простое
/*mem[0x3011]=*/ 0x0E03, // BRz NOT_PRIME ; Если R4 == 0, перейти к NOT_PRIME
/*mem[0x3012]=*/ 0x1A20, // ADD R2, R2, #1 ; Увеличить делитель на 1
/*mem[0x3013]=*/ 0x1C21, // ADD R3, R2, #0 ; Скопировать R2 в R3 для проверки конца цикла
/*mem[0x3014]=*/ 0x1C83, // ADD R4, R1, R3 ; Если делитель > корня R1, выход из цикла

/* Повторение цикла */
/*mem[0x3015]=*/ 0x0FEA, // BR LOOP_START ; Вернуться к началу цикла для следующего делителя

/* Если число является простым */
/*mem[0x3016]=*/ 0x5001, // ADD R0, R0, #1 ; Установить R0 = 1 (простое число)
/*mem[0x3017]=*/ 0xF021, // TRAP x21 ; Вывести 1
/*mem[0x3018]=*/ 0xF025, // HALT ; Остановить программу

/* Если число не является простым */
/*mem[0x3019]=*/ 0x5000, // AND R0, R0, #0 ; Установить R0 = 0 (не простое)
/*mem[0x301A]=*/ 0xF021, // TRAP x21 ; Вывести 0
/*mem[0x301B]=*/ 0xF025, // HALT ; Остановить программу
};

Программа зациклилась, ввожу значение в консоль, оно в ответ дублирует его, где ошибка?
  • Вопрос задан
  • 92 просмотра
Пригласить эксперта
Ответы на вопрос 1
@AlexandrBrown
И такс начнем:

В строках 0x300E, 0x300F и 0x3010 программа использует сложение и отрицание для проверки остатка. Вместо этого попробуй использовать команду MOD или корректную операцию для деления, чтобы проще вычислять остаток.
Убедсь, что после вычитания в R4 действительно остаётся 0, если число делится без остатка.
Условия выхода из цикла:
В строке 0x3014 (команда ADD R4, R1, R3) происходит проверка делителя на превышение корня числа R1. Здесь может возникнуть ошибка: после увеличения R2, R3 следует проверить, не достиг ли он значения, превышающего половину R1. Если это так, программа должна выйти из цикла.

Использование метки для выхода:

Команда BR LOOP_START (строка 0x3015) ведёт обратно в начало цикла, даже если число уже определено как простое или составное. Чтобы выйти из цикла в случае определения, что число не простое, замени её на условный переход к меткам PRIME или NOT_PRIME.
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы