Данному образовательному сайту пришлось несколько раз менять свое имя. С 2022 года доступ к нему обеспечивается по URL
emc.orgfree.com

emc.km.ru (2001-2007) ==> educomp.org.ru (2007-2011) ==> educomp.runnet.ru (2011-2021) ==> emc.orgfree.com (2022-...)
Более подробно об истории сайта можно прочитать здесь.


Учебные модели компьютера



Модели (software):

"Е14" (parallel !!!)
"S9PU" (parallel)

Модели (hardware):






Награды сайта
Награды сайта 2005

Программа "Календарь" (определение числа дней в месяце) рассматривает ячейку 01 как номер месяца и определяет количество дней в этом месяце.

Приводится два варианта решения. Первый - более простой - хранит количество дней в месяце в виде массива (последовательности чисел 31, 28, 31, 30, ...), и программа просто извлекает его элемент с нужным номером. Второй - логический - более сложный, но зато более короткий. Если к программе применимо понятие красоты (а по-моему, это так), то второй вариант несомненно красивее!

Вариант 1.

В памяти, начиная с ячейки 03 хранится 12 чисел, соответствующих количеству дней в каждом месяце. Программа к исходному номеру месяца прибавляет число на единицу меньше, т.е. 2 (дело в том, что месяцы нумеруются с 1, поэтому без этой коррекции для января получалось бы 3 + 1 = 4, для февраля 3 + 2 = 5 и т.д., т.е со сдвигом как раз на 1!) Полученное число записывается "внутрь" программы в качестве команды. Поскольку нулевому коду операции соответствует извлечение содержимого ячейки на сумматор, то сформированная команда достанет нужный элемент массива.

Например, для заданного в таблице случая n = 6 (июнь), получим 002 + 006 = 008, т.е. фактически команду 0 (первая цифра) извлечения из памяти содежимого ячейки 08 (две последние цифры). Проверьте и убедитесь, что в этой ячейке лежит информация именно для июня.
адрескодмнемоникакомментарии
n:n - номер месяца!
01006dw 6 исходная переменная n, для примера взято значение 6
a0:адрес начала массива (a0 = days - 1)
02002dw a0 (потребуется для формирования команды)
days:массив количества дней (dw 31, 28, 31, 30 ...)
0301Fdw 31 первый элемент: число дней в январе
0401Cdw 28 второй элемент: число дней в феврале
0501Fdw 31 третий элемент: число дней в марте
0601Edw 30 четвертый элемент: число дней в апреле
0701Fdw 31 (май)
0801Edw 30 (июнь)
0901Fdw 31 (июль)
0A01Fdw 31 (август)
0B01Edw 30 (сентябрь)
0C01Fdw 31 (октябрь)
0D01Edw 30 (ноябрь)
0E01Fdw 31 двеннадцатый элемент - количество дней в декабре
begin:начало программы
0F001lda (n) извлечь n
10A02add (a0) прибавить адрес начала массива
11112sta (command) записать полученное число как команду
command:формируемая команда
1200xlda (00x) (команда извлечения нужного элемента;
например, для июня 00x = 002 + 006 = 008)
13C00iprt вывести результат на экран
14F00hlt останов (стоп)

Это не баннер, а картинка по поводу задачи!

Вариант 2.

Посмотрим внимательно на подготовленную ниже таблицу, в которой для каждого месяца выписан его двоичный номер и количество дней:
месяцянв.фев.мартапр.майиюньиюльавг.сен.окт.нояб.дек.
дней 31 28 31 30 31 30 31 31 30 31 30 31
номер2 0001 0010 0011 0100 0101 0110 0111 1000 1001 1010 1011 1100

Если не обращать внимания на февраль, то можно заметить четкую связь между количеством дней в месяце и состоянием старшего (3-го) и младшего (0-го) битов его номера, а именно: в месяце 31 день, если эти биты различны и 30 - если одинаковы! (Проверьте, что это так.) Воспользуемся этим фактом при написании программы.

Прежде всего отметим, что для сравнения битов существует специальная логическая операция, которая называется исключающее ИЛИ. К сожалению, у "Малютки" она отсутствует, поэтому придется ее заменить на сложение битов с игнорированием возникающего переноса (чтобы сделать это, достаточно в результате суммирования стирать все биты, кроме 0-го), т.е.:
0 + 0 = 00 + 1 = 1 1 + 0 = 11 + 1 = 0

Таким образом, остается вычислить по указанным правилам сумму 3-го и 0-го битов и к результату просто прибавить 30!

Разумеется для февраля придется количество дней рассчитывать отдельно. Если бы не это "досадное исключение", программа была бы еще короче!

адрескодмнемоникакомментарии
n:n - номер месяца!
01006dw 6 исходная переменная n, для примера взято значение 6
02802dw -2 для февраля (константа min2)
03001dw 1 для выделения младшего бита (константа mask)
0401Edw 30 количество дней (константа day0)
begin:начало программы
05001lda (n) извлечь n
06A02add (min2) n - 2 (сравнение с февралем)
07E0Fjz printfeb переход, если февраль (к 0F)
08001lda (n) извлечь n       (xxxx xxxx Bxxx)
09310sar сдвиг вправо (xxxx xxxx xBxx)
0A310sar сдвиг вправо (xxxx xxxx xxBx)
0B310sar сдвиг вправо (xxxx xxxx xxxB - 3-й бит попал в 0-й)
0CA01add (n) сложить этот бит с 0-м у исходного числа
0D803and (mask) оставить только младший бит
0E410jmp daleeобход ветки февраля (к 10)
printfeb:для февраля взять -2, т.к. 28 = 30 - 2
0F002lda (min2)поместить в СМ константу -2
dalee: 
10A04add (day0) СМ + 30 - получим количество дней
11C00iprt вывести результат на экран
12F00hlt останов (стоп)

Я надеюсь, что при реализации второго варианта Вы, как и я, получили определенное интеллектуальное удовлетворение от подтверждения на практике довольно абстрактных рассуждений о битах!


© Е.А.Еремин, 2001


Автор сайта - Евгений Александрович Еремин (Пермский государственный педагогический университет). e_eremin@yahoo.com


Free Web Hosting