iЮГ-3. Итоги конкурса

С чувством глубокого удовлетворения можно констатировать, что объявленный мной в рамках рубрики конкурс успешно состоялся. Хотя был он не из простых. Однако участники нашлись, и было из кого выбирать победителей. Более того — результаты меня удивили. Но обо всём по порядку.

Напомню, что конкурс состоял из двух независимых частей, теоретической и практической. Так вот, в теоретической — более простой — части победителей не получилось. (:

Задание первое там заключалось в ответе на вопрос: „сколько контактных ножек (без мультиплексирования и комбинирования) должна иметь микросхема процессора 4917, чтобы обеспечивать его функционал, как он описан в руководстве и реализован в приложении?“ Ответы показали, что народ не очень представляет себе логику работы цифровых микросхем. Поэтому приведу свой вариант ответа и заодно об этой логике расскажу.

Ну да, процессор четырёхразрядный, поэтому ему нужно четыре ноги на адресную шину и четыре ноги на шину данных. В этом-то правы были все. А вот зачем ему нужна третья шина — для принтера — я не понял. На принтер-то уходят те же самые данные! (: Правда, чтобы они ушли именно на принтер, нужно кое-что дополнительное, и скоро мы до этого дойдём.

Ещё три ноги, без которых совсем никак — это земля, питание и управление внешним устройством (цепью звонка). Тут тоже догадались. А вот про сигналы тактовой частоты, для которых нужна ещё одна нога, почему-то не подумал никто! Давайте про это подробнее.

Видели дирижёра перед оркестром? Не может быть, чтобы не видели ни разу. А как он работает? Руками подаёт какие-то знаки музыкантам. В его дирижёрском арсенале много разных жестов, но одно в этих помахиваниях незыблемо и обязательно. Движения руками (или, по крайней мере, одной рукой) вверх-вниз задают всему оркестру темп игры. Чтобы у всех музыкантов один такт в нотах длился одно и то же время. А когда дирижёр военного оркестра идёт или стоит к своим музыкантам спиной — он задаёт этот темп вертикальными взмахами специального жезла. Если оркестр большой — взмахи могут дублировать такими же жезлами ассистенты. Чтобы музыканты видели, не напрягаясь.

itogi-yug

Так вот, в цифровой схемотехнике синхронность и согласованность работы отдельных компонентов обеспечивается тем, что все они получают периодические тактовые сигналы. Аналог дирижёрских взмахов. В конструкторской документации прописано, сколько тактов то или иное устройство выполняет свои действия или отводит другим устройствам на выполнение своих команд. Иногда на микросхему подводится несколько таких сигналов с разными частотами — но уж один-то должен быть обязательно!

Чуть поконкретнее. Вот команда с кодом 7 подаёт сигнал на включение внешнего устройства (звонка). Для этого должно появиться оговоренное напряжение (разность потенциалов с землёй) на соответствующей ноге. А на сколько оно должно там появляться? Очевидно — не навсегда, но на достаточное время, чтобы контроллер этого устройства заметил сигнал и отреагировал на него. Допустим, конструктор пишет в документации — на две миллисекунды. Или ему сказали, что нужно именно столько. А как процессор будет эти две миллисекунды отсчитывать? Да вот по тактовым сигналам. Зная рабочую частоту, нужно просто умножить на неё время удержания сигнала, и через столько „тиков“ сигнал можно убрать.

И, кстати, отладочное замедление работы процессора, скорее всего, будет реализовано простым понижением тактовой частоты. Так что добавляем как минимум одну ногу.

А теперь ещё одну — установку режима, посредством которой заставляют процессор работать в трассировочном режиме вместо обычного. Хоть одна, но понадобится.

Итого уже тринадцать: четыре шина данных, четыре адресная шина, земля, питание, внешнее устройство, тактовая частота, режим работы.

Теперь самое забавное. Открою страшную тайну: микропроцессор не умеет читать мысли, и другие устройства не умеют читать его мысли. (: У него, если что, мыслей вообще нет.

Это я вот к чему. Отправляя данные на шину, процессор должен сказать, куда они идут — в память или на принтер? Должен. Добавляем ногу „память/принтер“. Четырнадцать.

Это не всё. Пусть нужна работа с памятью. Как контроллер памяти должен понимать свою задачу? Что он должен делать с адресом, полученным по шине? Взять число с шины данных и записать его по этому адресу? Или взять число по этому адресу и подать его на шину данных? Чего хочет процессор? Добавляем ногу „чтение/запись“. Пятнадцать.

Но даже это ещё не всё. Осталось самое тонкое. Внешние устройства не работают беспрерывно. Когда процессор занят, например, арифметикой, ему от контроллера памяти с принтером ничего не нужно. И им надо это объяснить. Добавляем ногу „занят/жду“. Принтер и/или контроллер памяти должны начинать свою работу, только получив сигнал с этой ноги! Шестнадцать.

Итого:

  • Общее функционирование процессора — земля, питание, частота, режим — четыре ноги.
  • Адресная шина — четыре ноги.
  • Шина данных — четыре ноги.
  • Управляющие сигналы — сигнал внешнему устройству, память/принтер, чтение/запись, занят/жду — четыре ноги.

Шестнадцать контактных ножек, и это по минимуму, и это без ненужной „шины принтера“.

Со вторым теоретическим заданием дело обстояло несколько лучше. Но не намного. (: Напомню, нужно было предложить наиболее интересную и полезную замену для команды с кодом 7 (подающей сигнал на замыкание цепи внешнего устройства). Причём замена должна была быть реалистичной командой одинарной длины.

Я не буду подробно перечислять и разбирать заведомо нереальные варианты, остановлюсь лишь на одном. Просто потому, что чего-то такого я ждал. И получил. Была предложена команда SWAP, меняющая значения регистров R0 и R1.

Штука, безусловно, полезная. Но почему она нереальна? А потому, что поменять местами два значения можно лишь двумя способами. Первый — с использованием третьей локации для промежуточного хранения. Но 4917 не имеет ни стека, ни третьего регистра общего назначения! Не позволять же ему ради этого гадить память, в самом-то деле. Второй способ — через трёхкратное XOR („исключающее или“) над битовым представлением меняемых величин. Это несколько более реалистично, но медленно, и 4917 устроен так, что результат всегда помещается в R0, а тут одна из трёх операций обязана поместить его в R1. Увы, не проходит.

Реалистичные замены для седьмой команды были, но отдать кому-то приз я не счёл возможным. Потому что автор самого реалистичного варианта (сбросить R0 в нуль) и так обязан был получить приз за решение задачи, а два приза в одни руки не положено. (:

Переходим, собственно, к задачам. Их было две, причём первая заметно полегче. Там требовалось вывести все нечётные числа диапазона 0-F в порядке убывания, то есть

F D B 9 7 5 3 1

Решил только один человек, и то способом, далёким от оптимального (использовал 13 из 16 ячеек памяти). Хотя, ничего не скажешь, решил честно.

Моё решение на четыре ячейки короче:

5B48 05F0 0000 0000

А вот его расшифровка мнемоникой:

0: 5    DEC R0
1: B4   MOV (4),R0
3: 80   PRINT 0
5: 5    DEC R0
6: F0   JMPNZ 0
8: 0    HALT

По-моему, довольно просто.

Вторая задача была сильно хитрее. Напоминаю формулировку:

По известному адресу в памяти (его выбираете вы сами) перед запуском помещают число. Программа должна выдать на печать все шестнадцатеричные числа диапазона 0–F, за исключением одного этого числа.

Эта формулировка содержит один очень характерный для меня момент. Читаем внимательно. Там хоть где-нибудь сказано, что печать должна выполняться в каком-то порядке? (: Добавлять это условие означает очень сильно усложнять задачу. Я её в таком виде даже обычно и не даю, потому что школьники не решат же, хотя решение есть.

А если подходить чисто формально, то вот моё решение:

A965 ECC9 8*D2 0000

Звёздочкой отмечено место, куда надо перед запуском поместить число-исключение.

Участница конкурса по имени Анастасия Головина эту тонкость в условии заметила и представила решение, практически аналогичное моему:

9AA9 56C9 8*F2 0000

Расшифровку представлять не буду. И так видно невооружённым глазом, что местами куски кода просто совпадают. Анастасии и достался один из двух призов!

А вот участник, представившийся как Azat M, задачу себе усложнил. Но решение для этого усложнённого варианта нашёл, и отличное решение!

AF2E 7809 63B6 F20*

Выводит числа по возрастанию, плюс сохраняет память в её первоначальном состоянии. Добавить абсолютно нечего, кроме расшифровки:

0: AF   MOV R1,(F)
2: 2    SUB
3: E7   JMPZ 7
5: 80   PRINT 0
7: 96   MOV R0,(6)
9: 3    INC R0
A: B6   MOV (6),R0
C: F2   JMPNZ 2
E: 0    HALT
F: *    ; data

Этому-то участнику и ушёл второй из двух призов. Всем остальным — большое спасибо! Ну… а кому понравилось, вот ещё задачка вне конкурса:

Программа должна выдать на печать свой собственный машинный код, каким он был в момент запуска.

Решение существует. (:

Добавить комментарий

Ваш адрес email не будет опубликован.