Прошло очень много лет. То ли из-за нехватки отладочной платы с ПЛИС, то ли по каким-то другим причинам. Но, мечта остаётся мечтою. Даже эмулятора нет...
Именно "РАДИО-86РК" интересен тем, что, отлично от "Специалиста" или "Ориона-128", в нём нет графической памяти. А значит, вся память может использоваться под нужды пользователя в рамках одной страницы.
К тому же, К580ВМ80А позволяет организовать т.н. Гарвардскую архитектуру: Разделить стек, данные и код на три независимые страницы. На сколько я понял из справочников, процессор периодически в шину данных посылает слово статуса: Цикл M1; Чтение/запись данных; Обращение к стеку. Тем самым, это уже не 64кб, а 192кб памяти, без всяких переключений страниц.
После сброса, к шине процессора подключается К155РЕ3 до тех пор, пока в цикле M1 не произойдёт чтение команды из старшей половины памяти:
Code: Select all
0000..7FFF M1 - ROM-К155РЕ3
0000..FFFF WR - RAM-64K
Code: Select all
0000: 21 00 E0 | MOV BX,0xE000 ; Адрес внешнего ПЗУ
0003: F9 | MOV SP,BX ; Стек будет источником файла BIOS
0004: D1 | POP DX ; Читаем слово из ПЗУ
0005: 73 23 | MOVS [BX],DL ; Записываем его по тому адресу,
0007: 72 23 | MOVS [BX],DH ; но в память ОЗУ
0009: 7C | MOV AL,BH ; Проверим, не вышел ли указатель
000A: 87 | ADD AL,AL ; за границы в 64Кб?
000B: DA 04 00 | JC 0x0004 ; Продолжаем заполнение памяти
000E: EB | XCHG DX,BX ; Последнее слово - адрес старта
000F: E9 | JMP BX ; Передаём управление "Монитору".
Следует отметить, что стек здесь физически обеспечивает доступ к внешним устройствам (ВТ57, ВГ75, ВИ53, ВВ55). Так как прикладная программа не может постоянно менять режимы работы ВГ75 или ВИ53, доступ к ним через стек в этом случае достаточно оправдан.
Допустим, основная процедура инициализации дисплея теперь выглядит несколько громоздко и странно:
Code: Select all
FACE: E5 C5 | PUSH BX,CX ; Сохраняем регистры
FAD0: 21 00 00 | MOV BX,0x0000 ; Очищаем регистры
FAD3: 44 4D | MOV CX,BX
FAD5: 39 | ADD BX,SP ; Запоминаем указатель стека
FAD6: 31 12 C0 | MOV SP,0xC012 ; ВГ75: Вместо C001 - C010
FAD9: C5 | PUSH CX ; Записываем нули
FADA: 01 1D 4D | MOV CX,0x4D1D ; Вместо C000 - C000..C00F
FADD: C5 | PUSH CX
FADE: 01 93 99 | MOV CX,0x9993
FAE1: C5 | PUSH CX
FAE2: 31 12 C0 | MOV SP,0xC012
FAE5: 01 27 27 | MOV CX,0x2727
FAE8: C5 | PUSH CX
FAE9: F1 | POP PSW
FAEA: 3B | DEC SP
FAEB: 3B | DEC SP
FAEC: E6 20 | AND AL,0x20
FAEE: CA E9 FA | JZ 0xFAE9
FAF1: 31 12 E0 | MOV SP,0xE012 ; То же самое с ВТ57
FAF4: 01 80 80 | MOV CX,0x8080 ; Вместо E008 - E010
FAF7: C5 | PUSH CX
FAF8: 31 0A E0 | MOV SP,0xE00A ; Вместо E004 - E008
FAFB: 01 76 D0 | MOV CX,0xD076
FAFE: C5 | PUSH CX
FAFF: 31 0C E0 | MOV SP,0xE00C ; Вместо E005 - E00A
FB02: 01 49 23 | MOV CX,0x2349
FB05: C5 | PUSH CX
FB06: 31 12 E0 | MOV SP,0xE012
FB09: 01 A4 A4 | MOV CX,0xA4A4
FB0C: C5 | PUSH CX
FB0D: F9 | MOV SP,BX
FB0E: C1 E1 | POP CX,BX
FB10: C9 | RET
Так, в архитектуре i8080 (Z80) мне не нравится следующее:
Команда 31 или F9 - указатель стека не так часто устанавливается. Можно было бы обойтись долгим циклом с 33 или 3B;
Команда E9 - можно было бы просто обойтись парой E5 C9.
(На эту тему я часто говорю на форумах относительно x86, где уйма мусорных AAA/AAD/AAM/AAS имеют по байту, а используются крайне редко.
У процессоров Intel это очень больная тема: Куча дурацких команд имеют компактные коды.
Таким образом, теоретически на ВМ80 (Z80) можно построить систему, где ОЗУ покрывает всё адресное пространство. А стек покрывает лишь младшую половину ОЗУ. Старшая предназначается под доступ к внешним устройствам.
Можно, конечно, возразить. Мол, опрос клавиатуры станет чудовищно сложным.
Ну я же не говорю о полной совместимости с РК. Опрос клавиатуры можно возложить на ПДП. Если её посадить на шину адреса (как в ZX) и считывать аппаратно состояние клавиш прямо в память.
Здесь, скажем, адреса матрицы клавиш будут 7F,BF,DF,EF,F7,FB,FD,FE в дампе из 256 байт.
Вот про ПДП
Также INT (RST) команды в данный момент прорабатываются. Так, RST 0 (C7) никогда не используется, так как стартует с 0000. Кажется, я нашёл способ обойти это препятствие:
Code: Select all
0000: F5 |PUSH PSW ; Нужно убедиться, что это -
0001: E5 |PUSH BX ; вызов RST 0, а не старт G0.
0002: 21 FF 89 |MOV BX,0x89FF ; Проверяем по указателю стека.
0005: C3 _G0_ |JMP _G0_
.............. ..............
_G0_: 39 |ADD BX,SP ; Если стек уже иницирован этой
+001: E1 |POP BX ; данной программой, он будет
+002: D2 _C7_ |JNC _C7_ ; меньше 0x7600
+005: 31 00 76 |MOV SP,0x7600 ; Иначе, это старт - G0.
.............. ..............
_C7_: F1 |POP PSW ; Теперь, можно обрабатывать C7
+001: D2 11 +0 |JZ +011 ; Если условие не выполняемо
+004: E3 |XCHG BX,[SP] ; Извлекаем адрес возврата
+005: F5 C5 |PUSH PSW,CX ; Сохраняем всё необходимое
+007: 4E |MOV CL,[BX] ; Извлекаем байт смещения
+008: 79 |MOV AL,CL ; Здесь мы выполняем
+009: 87 |ADD AL,AL ; аналог
+00A: 9F |SBB AL,AL ; x86-инструкции
+00B: 47 |MOV CH,AL ; MOVSX CX,CL
+00C: 09 |ADD BX,CX ; Смещаем IP на указанную
+00D: C1 |POP CX ; величину
+00E: 23 |INC BX ; Коррекция, т.к. прочли
+00F: E3 |XCHG BX,[SP] ; относительный адрес
+010: C9 |RET ; Получился аналог JR NZ (Z80)
+011: E3 |XCHG BX,[SP] ; Условие не выполнилось
+012: F5 |PUSH PSW ; Пропускаем байт относительного
+013: C3 0E +0 |JMP +00E ; перехода по условию
Таким же образом реализуются JR Z, JR C и JR NC. Остальные RST выполняются в том же духе.
Например, BF F7 и 37 F7 - снимается/предустанавливается флаг CF, который можно использовать как переключатель. Скажем,
BF F7 - CALL 0xF812
37 F7 - CALL 0xF803
AF F7 - CALL 0xF81B
Целых три разных вызова...
M1 через ПЗУ:
Как-то была идея аппаратно пропускать байт инструкции через ПЗУ, где коды команд несколько упорядочить на свой лад:
При взломе программа будет выглядить неузнаваемо. Здесь я строил таблицу по принципам:
1. Код 00 в текстовых файлах, обычно, означает конец. А конец программы - HLT;
2. Код 80 - десятичное -128, которое не имеет отрицательного значения (-128 = NEG(-128)). Значит, пустая операция;
3. Холостые пересылки (MOV B,B/MOV C,C/MOV D,D и т.д.) работают как префикс подмены аккумулятора в вычислениях (mov b,b + ora a = orb a или mov d,d + cma = not d)
4. Команды из 2-х и 3-х байт сложены в стопку. Что упрощает дешифрацию (ассемблинг/дизассемблинг).
Так как я давно имею мечту разработать для ПЛИС свой вариант процессора на базе i8080, то систему команд можно переработать произвольно. А таблица - один из вариантов.