Сборка Z80 (1 МГц) CP / M: Как получить правильный физический ввод с помощью кнопок - PullRequest
0 голосов
/ 04 ноября 2018

Я новичок, изучающий информатику. В области компьютерной техники мы работаем над 8-разрядным микропроцессором Zilog Z80 (1 МГц) и набором компонентов, которые необходимо вручную подключить с помощью макета и кабелей.

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

Я уже прочитал руководство и знаю набор инструкций, которые можно использовать (только самое необходимое). Для начала, я не пытаюсь получить самый чистый, самый красивый код из возможных; но не волнуйтесь, позже я это сделаю, потому что мне нравится чистый и эффективный код.

На данный момент программа работает хорошо в симуляторе, поэтому синтаксис в порядке. Тем не менее, я не уверен, как справиться с некоторыми логическими проблемами.

Упражнение имеет следующие характеристики:

  1. Начальный адрес RAM: E000h
  2. Входной порт 1: 03h
  3. Выходной порт 1: 05h
  4. Отображение ввода / вывода для портов
  5. Цепи автоматически разомкнуты (1), поэтому светодиоды НИЗКО активны (0)
  6. Вход 2,3,4 изменяет поведение движения светодиодов
  7. Ввод 5,6 изменения частоты мигания светодиода

Я установил начальный адрес с помощью ORG E000h и инициализировал указатель стека с помощью MOV SP,FFFFh. Для входа (три разных типа мигания / бега, а также две разные частоты, всего пять кнопок) я создал разные метки.

Моя проблема на данный момент в том, что я не совсем уверен, как правильно настроить физический ввод - IIRC, мне нужно было бы указать битовую комбинацию, используя XOR со всем, равным 1, но желаемым входом, чтобы я мог используйте информацию в моей программе.

Но хотя я знаю, как это должно работать (по крайней мере, я думаю, что знаю), я не могу полностью обернуться вокруг реализации программного обеспечения. Кроме того, у меня проблемы с условиями: нажатие одного переключателя изменяет частоту мигания на 1/4 Гц, а нажатие другого переключает на 4 Гц. На языках более высокого уровня я бы просто использовал IF / ELSE здесь, но я не знаю, как это сделать в этом случае - к сожалению, руководство включает только основные операции, поэтому я в растерянности.

Поэтому я решил попытать счастья и обратиться к сообществу за помощью.

Для тех, кто заинтересован, я выложу свой код. Как я уже упоминал, это очень просто, но мне просто нужно, чтобы работа была выполнена на данный момент. Поскольку я не фанат огромных кусков неуклюже отформатированного кода, я разместил файл здесь . Файл представляет собой * .txt, размещенный через GoogleDrive.

Спасибо за ваше время и хорошего дня!

[РЕДАКТИРОВАТЬ] добавил специальный код в пост, в соответствии с вводом пользователя Рууд Хелдерман

[РЕДАКТИРОВАТЬ] обновленный код в * .txt-файле - теперь проще и эффективнее

[EDIT] использовал HTML-форматирование для выделения директив в записи

Фрагмент кода:

blink:       ;function: all LED blinking, activated via input[2]
MOV A,FFh
OUT 05h,A     ;all LED out
CALL pause1   ;frequency 1/4Hz, activated via input[5]
MOV A,00h
OUT 05h,A     ;all LED on
CALL pause1
JP blink      ;jump back to begin of function

Вышеуказанная функция изменяет поведение светодиода (в данном случае: мигание), а также частоту, используя различные физические переключатели на плате входных переключателей с общим количеством переключателей восемь (от 1 до 8, состояние неактивности = 1; используются переключатели от 2 до 6) , Я знаю, что получение входных данных должно быть простым делом - это просто вопрос использования XOR с битовой комбинацией 0 и ровно одного 1.

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

Я вполне осознаю, что это, вероятно, тривиальный вопрос, и, может быть, я просто застрял в ментальном цикле, который я создал, задумавшись, но в данный момент я не знаю, как добраться, где мне нужно быть (хотя я вижу замок на горизонте - спасибо, Кафка!).

Любая помощь очень ценится.

Ответы [ 2 ]

0 голосов
/ 10 ноября 2018

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

Проблема, как я и предполагал, была связана с тем, что я застрял в заблуждении, которое, к счастью, было исправлено моим партнером по лаборатории. Итак, в конце концов, мы смогли заставить нашу программу работать - в последнюю минуту и ​​не на все 100%, но она работала и отвечала требованиям.

Так в чем же было мое заблуждение? Достаточно забавно, я знал, куда мы должны были пойти, и идея была правильной. Проблема заключалась в том, что я пропустил большую часть логической операции - я уже рассчитал ее в своей голове, а затем объединил фактическое рабочее решение с устаревшим AND, который разрушил функциональность.

В целом правильная комбинация XOR и AND была следующей:

programloop:
MOV A,40h       ;state of button 2, inverted (XOR FFh)
MOV B,A         ;save state to register B
IN A,03h        ;input at port-address 03h
AND B           ;find out if button is pressed
JPNZ blink      ;if yes, jump to blink

MOV A,20h       ;state of button 3, inverted (XOR FFh)
MOV B,A         ;save state to register B
IN A,03h        ;input at port-address 03h
AND B           ;find out if button is pressed
JPNZ goright    ;if yes, jump to goright

MOV A,10h       ;state of button 4, inverted (XOR FFh)
MOV B,A         ;save state to register B
IN A,03h        ;input at port-address 03h
AND B           ;find out if button is pressed
JPNZ goleft     ;if yes, jump to goleft
JP programloop  ;go back to beginning (input has to be checked constantly)

Это помогло трем кнопкам, которые изменили поведение светодиодов.

Что касается частоты, нам пришлось снизить сложность всего до двух состояний из-за нехватки времени (мы неправильно прочитали задание и ошибочно начали с вопроса о бонусе, который стоил нам около 50% времени на разработку - ура. Урок. узнал: всегда начинай читать сверху и читай внимательно .)

Но так как изменение частоты сработало, оказалось, что все в порядке.

MOV A,03h       ;state of button five being pressed (inverted)
MOV B,A         ;saved state into register B for later use
IN A,03h        ;physical input over button
AND B           ;find out if button is pressed
JPNZ freq025Hz  ;if yes, jump to freq025Hz
JPZ freq4Hz     ;if no, jump to freq4Hz

Вот и все!

Еще раз спасибо всем за помощь.

Если остались какие-либо вопросы, не стесняйтесь задавать!

0 голосов
/ 05 ноября 2018

Перво-наперво: если вы используете MOV, то вы, вероятно, используете синтаксис 8080, а не синтаксис Z80. По историческим правовым причинам Z80 не только расширяет язык ассемблера 8080, но и переименовывает всю существующую мнемонику (например, от MOV до LD). Если вы ищете код Z80 и находите инструкции, которые вы не можете распознать, это, вероятно, будет частью этого.

Обычный способ реализации условных выражений типа / else:

  1. выполнить любую операцию, которая соответствующим образом устанавливает флаг состояния; и
  2. используйте один из условных переходов, чтобы пропустить некоторый код или нет, в зависимости от флага состояния.

В вашем случае вы хотите что-то делать или не делать что-то в зависимости от того, установлен ли бит, поэтому один из способов сделать это - ANI (z80: AND). Это вычисляет логическое значение и аккумулятора и операнда, сохраняя его в аккумуляторе, но среди прочего оно также устанавливает нулевой флаг. Таким образом, вы можете использовать JNZ (/ JP NZ) и JZ (/ JP Z), чтобы что-то делать или нет, в зависимости от того, установлен ли бит. Э.Г.

; upon entry, A has an unknown value, loaded from somewhere.

ANI 08h    ; Set a = a & 8; so either bit 2 was originally set and a now
           ; has the value 8, or bit 2 wasn't set and a now has the value 0.

           ; Also: the zero flag is now set if a is zero, reset otherwise.

           ; So you've loaded NOT (a.bit2) into the zero flag.

           ; You've also lost the rest of the accumulator, but such is life.
           ; Keep a copy somewhere, or grab it again via IN as required.

JZ bitnotset

; code here will be performed only if bit 2 was originally unset.

bitnotset:

; this code will happen regardless of whether bit 2 was set.

Мне не известно о TEST в синтаксисе в стиле 8080 или Z80.

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

...