PDA

Просмотр полной версии : Специалист: программирование на ассемблере



CityAceE
27.12.2023, 13:10
Всеми силами пытаюсь привлечь внимание людей к этой, теперь уже почти забытой, платформе. Сделал вот такой экспериментальный ролик. Судя по статистике, мои ролики на YouTube в основном смотрят совершенно случайные люди возрастом до 30 лет, которым YouTube их иногда рекомендует. Вот на таких людей я и нацеливался. А форумчане, скорее всего ничего нового и интересного там не увидят. Но на всякий случай ссылку на ролики всё-таки выкладываю и на форуме тоже:


https://youtu.be/rmewRsTr4tw

Zidane
27.12.2023, 15:52
Ну нет... Неправда. Это пока что они случайные, потом норм пойдет. Я тут кривой ролик про 86РК запилил, все равно аншлаг сорвал....

HardWareMan
27.12.2023, 17:04
CityAceE, показываешь то Спеца, а асм и мнемоники юзаешь Z80. А потом из заглянувших почитает про Z80, понапишет под z80 прогу и она станет тыквой на Спеце с его ВМ80. И бросит это дело человек навсегда разочаровавшись в себе. Эх.

Zidane
27.12.2023, 17:30
Лично меня радует тот факт, что человек показывает кроссассемблер и как с ним работать. В принципе, аналоги мнемоник для Кр580ВМ80А можно и подобрать. Они все у Z80 есть, 16-ричные команды, насколько я знаю, кроме некоторых недокументированных, совпадают. Так что частности. Потому, если писать исключительно на аналогах мнемоник по таблице команд, проблем особых быть не должно. Почти все новые команды Z80 по моему через префиксы добавлены. Или я ошибаюсь? Ну хотя я то все равно в мнемониках Кр580 работаю. Но надо озадачится этим моментом....

ivagor
27.12.2023, 18:21
Если точно следовать указаниям из видео (https://youtu.be/rmewRsTr4tw?t=923), то не получится откомпилировать с помощью sjasmplus программу, которая использует команды отсутствующие у 8080. Но проблема в другом - человек, который не знаком с 8080, скорее всего попробует что-то узнать про него из книг по 8080, а там мнемоники 8080 и ему sjasmplus мягко говоря не очень подойдет. А если изучать 8080 по книгам про z80, тут тоже ситуация не очень хорошая, там далеко не всегда пишут, каких команд не было у 8080.
На мой субъективный взгляд такой подход (с мнемониками z80 и sjasmplus) подойдет для уже знакомого с ассемблером z80, но для них такое видео пожалуй слишком простое и им нужно что-то то более замысловатое.

CityAceE
27.12.2023, 22:55
Друзья, с вами целиком и полностью согласен, что плохо, что я показывают программирование под КР580ВМ80А (i8080), но при этом использую мнемоники Z80. Вы скорее всего не посмотрели моё видео, но я там сетую на это и говорю, что это, конечно же, неправильно. Но я действительно просто начисто забыл мнемонику i8080! Я пытался как-то восстановить утраченные знания, но они, к сожалению, уже никак не приживаются - мозги уже совсем не те. Поэтому я решил сделать так, как умею и делаю сам. Благо, подписчиков у меня практически нет, а просмотров моих роликов крайне мало. Так что какой-то ощутимый урон я вряд ли нанесу. Но я очень надеюсь, что пару-тройку случайных человек мне всё-таки удастся заинтересовать. Обидно, что люди, которые реально обладают недюжинными знаниями, не делают подобных обучающих роликов. Я бы с удовольствием поучился бы у того же ivagor'а или svofski. Но, к сожалению, не все мэтры готовы тратить время на видеоролики. Поэтому я в силу своих знаний и возможностей хоть как-то стараюсь восполнить данный пробел.

В следующем ролике, если он будет, я обязательно ещё раз акцентирую на разницу мнемоник.

svofski
27.12.2023, 23:25
Обидно, что люди, которые реально обладают недюжинными знаниями, не делают подобных обучающих роликов.
Есть очень хороший семинар от parallelno, в котором все хорошо с мнемоникой: https://www.youtube.com/watch?v=yeffgNz69lI

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

HardWareMan
28.12.2023, 06:58
Вы скорее всего не посмотрели моё видео, но я там сетую на это и говорю, что это, конечно же, неправильно.
А мало сетовать, если преследуешь академический интерес. Нужно делать правильно.

Но я действительно просто начисто забыл мнемонику i8080! Я пытался как-то восстановить утраченные знания, но они, к сожалению, уже никак не приживаются - мозги уже совсем не те.
А ведь журнала Радио для этого вполне хватает. Всего одного цветного разворота, на главную часть которого я делал перерисовку...
https://i.postimg.cc/525BxM7n/1.png
https://i.postimg.cc/tg2FxNH6/2.png

Поэтому я решил сделать так, как умею и делаю сам. Благо, подписчиков у меня практически нет, а просмотров моих роликов крайне мало. Так что какой-то ощутимый урон я вряд ли нанесу. Но я очень надеюсь, что пару-тройку случайных человек мне всё-таки удастся заинтересовать.
Тем не менее, ты его нанесёшь. А можно было избежать совсем.

Обидно, что люди, которые реально обладают недюжинными знаниями, не делают подобных обучающих роликов. Я бы с удовольствием поучился бы у того же ivagor'а или svofski. Но, к сожалению, не все мэтры готовы тратить время на видеоролики. Поэтому я в силу своих знаний и возможностей хоть как-то стараюсь восполнить данный пробел.
Да, мэтрам есть чем заняться, кроме роликов. Но можно же просто скооперироваться с ними и/или проконсультироваться у них. И потом снимать свои ролики уже с правильными данными. Ведь ты даже поди не пробовал спросить совета по своему проекту ролика.

В следующем ролике, если он будет, я обязательно ещё раз акцентирую на разницу мнемоник.
Нужно не акцентировать а делать. Лично я, например, использую TASM. У меня есть даже своя табличка, где есть мнемоники от i8080 но и расширенные для Z80 но в виде мнемоник i8080. Например, LXI IX,# или MOV MX,A/MOV MY,A.

- - - Добавлено - - -


Тревогу за зрителя, который посмотрел одно видео не с теми мнемониками, увидел в своем ассемблере другие и вот, его жизнь сломана навсегда, я не разделяю.
Это полбеды. Мой изначальный посыл про то, что смотрящий начнёт использовать IM 2, BIT 4,A и потом будет недоумевать, какого чёрта не работает? Потом найдёт отличия и будет пытаться запомнить, какие из LD есть а каких нет у ВМ80. Зачем, если можно просто показать 1 разворот из журнала Радио, в котором есть абсолютно всё!
https://i.postimg.cc/Njz3cMbv/Radio1.jpg

PS Для тех, кто не разумеет ангельский добавил перевод документа.

ivagor
28.12.2023, 07:08
Все зависит от приоритетов. Мои придирки более-менее справедливы, если в первую очередь видео обучающее. Тогда желательно сослаться на какой-нибудь учебник/книжку по z80, где хотя бы кратко упоминаются отличия от 8080. Могу вспомнить, что начинал учиться по книжке Инфоркома и даже для вектора некоторое время писал в мнемониках z80 и компилировал в тетрадке. Но довольно быстро размер программ вырос, я перестал страдать ерундой и стал компилировать в ассемблере (а для голого вектора есть ассемблер только с мнемониками 8080). Вероятно в Инфоркомовском учебнике упоминали про отличия z80 от 8080 или я сверял по таблице команд - уже не помню.
Возвращаясь к приоритетам - если в первую очередь видео развлекательное, то меня можно и даже нужно игнорировать. Как делать развлекательные видео я не знаю, и если что-то напишу на эту тему, то лучше сделать наоборот.

CityAceE
28.12.2023, 10:41
Не буду комментировать каждую фразу ибо сейчас развернётся срач. А кому он нужен? ;)

Я для себя много лет назад уяснил, что если хочешь добиться хоть какого-то результата, то не нужно ни с кем советоваться, а брать и делать всё самому, как ты это видишь, знаешь и умеешь. Пусть это будет даже криво. Как только начинаешь с кем-то советоваться, то практически со 100%-ной гарантией можешь быть уверен, что результата не будет никакого. У меня это подтверждается всегда и во всём. Сколько всего не увидело свет из-за попыток посоветоваться и желания сделать всё идеально! А думаете, был бы этот форум, если бы я предварительно с кем-то начал советоваться? Шанс, что форум будет поддержан общественностью, был минимальный, однако через пару недель форум отметит свой 19-й День Рождения. Это же касается и написания статей, и организации корпоративов и т.д., и т.п. Всегда найдутся люди, которые знают как надо сделать правильно. Но даже если сделать так, как говорят эти люди, всегда найдётся и те, кто скажут, что и так не правильно, а правильно только так, как говорят они.

Это вы ещё не знаете, как я собирался объяснять всё дальнейшее. Наверное, вообще камнями закидали бы... Безусловно, мне резко расхотелось что-то снимать дальше. И пока я не знаю продолжу ли. Но если вдруг продолжу, то ровно в том же самом стиле - так, как я знаю и умею. И ещё раз повторюсь, вы сильно переоцениваете влияние моих роликов на общественность - у меня крохотный канал с минимальными просмотрами. А тематика роликов, даже если их выпускать каждый день, не позволяет каналу как-то расти. Да и не ради количества просмотров я всё это делал...

Ну и никто же никому не запрещает сделать собственные ролики с правильным академическим походом. Да? Вот даже можно взять мой первый ролик и разнести его в пух прах, разложив всё по полочкам и на счёт правильных мнемоник, и на счёт неправильного компилятора и т.д. - такой тип роликов тоже довольно востребован в Интернете.

HardWareMan
28.12.2023, 11:07
CityAceE, ты не понял основной сути моего послания про совет. Конечно же я не имел в виду что делать именно так как советуют. Всего-лишь прислушиваться. А что касается "никогда не выйдет" - так может это у тебя гранаты не той системы? Мой опыт подсказывает, что когда я ни с кем не советуясь что-то проектирую то оно затягивается так, как раз в поисках идеала, что только те проекты, где в какой-то момент я себе сказал твёрдое: "СТОП, выпускаем как есть на данный момент!" и увидели свет. А так же все сторонние проекты с моим консультированием успешно реализованы людьми и некоторые даже коммерческие. Что касается форума, то я думаю это несколько некорректный пример, ибо форум наполняют пользователи а не админ. Работа админа лишь в задании тематического вектора на старте и поддержание его в процессе. Тема ZX в СНГ была животрепещуща и её явно ожидал успех. То, что она продержалась так долго - я удивлён и несомненно рад.

CityAceE
28.12.2023, 11:17
Что касается форума, то я думаю это несколько некорректный пример
Да нет, почему же? ZX-PK на тот момент был "ещё одним" форумом из тогда существовавших. Ну и после запуска тут же стали говорить, что и движок не тот, и разбивка по разделам не та, и вообще зачем этот форум нужен, если есть Форум A, Форум B и Форум С. Были претензии практически ко всему, начиная от оформления и заканчивая доменом. Если бы в тот момент я заранее закинул бы удочку, и спросил бы стоит ли заводить ещё один форум, и попросил бы порекомендовать движок, то тогда точно всё закончилось бы на этом.

svofski
28.12.2023, 11:52
Всегда найдутся люди, которые знают как надо сделать правильно.
Я как-то записал видео на минуту, где показал как двигать степпером в дисководе, подключив к соответствующим ножкам обычный энкодер. Типа смотрите как прикольно, крутишь ручку, двигается головка, прр прр. На меня набросился какой-то псих который вспомнил про какую-то перемычку, которой в своем дисководе я потом даже не нашел, которую я всенепременно должен был подробно расписать, потому что без нее ничего не заработает, а я должен немедленно прекратить дезинформировать!!! зрителей и вообще прекратить свое существование, судя по тону сообщения.

Пожалуйста, продолжай снимать.

Zidane
28.12.2023, 12:27
В общем, не буду добавлять ничего к вышесказанному... Комментарий, так сказать, на лично опыте: когда сделал серию роликов " Spectrum BASIС", каих только кирпичей не словил... В току таких советчиков. Нравится - делай. Тема то нужная, на самом деле, учитывая какой популярностью пользуется ролик по работе на ассемблере для Радио-86РК. А там инфы то: вызов нескольких подпрограмм и несколько функций редактора "Микрон". Так что не сомневайся, кто бы что не говорил. Как там "кто может-делает, кто не может - ищет отговорки".

puller
28.12.2023, 15:20
С удовольствием посмотрел ролик и жду следующего. Во-первых, мне приходилось много программировать в интелевской мнемонике и совсем не довелось познакомиться с мнемоникой Z80. Поэтому такие уроки воспринимаю весьма положительно. Во-вторых, у меня есть набор для сборки Специалиста, и появился мощный стимул наконец-то им заняться.

parallelno
30.12.2023, 03:26
CityAceE, очень здорово что ты записываешь видео и делишься знаниями! Жду продолжения!

CityAceE
09.01.2024, 18:13
Вторая часть моих потуг нести прекрасное в массы. Рекомендуемая скорость просмотра х1.5.


https://youtu.be/6EkkgW2Kxfg

gurfunkel
09.01.2024, 18:18
CityAceE, а что за игра в начале видео?

CityAceE
09.01.2024, 19:03
что за игра в начале видео?
Эта игра называется "Gold".

HardWareMan
10.01.2024, 06:24
CityAceE, всё круто, речи нет. Но увы, мнемоники Z80 на Специалисте у меня вызывают отторжение.

CityAceE
10.01.2024, 07:39
Но увы, мнемоники Z80 на Специалисте у меня вызывают отторжение.
Я уверен, что тоже бы негодовал, если бы сам программировал на Специалисте как положено, то есть в мнемониках i8080.

HardWareMan
10.01.2024, 11:45
Я уверен, что тоже бы негодовал, если бы сам программировал на Специалисте как положено, то есть в мнемониках i8080.
Просто это началось в 1988 году и непрерывно продолжалось практически до 1994. А потом от случая к случаю. Поэтому, это сродни ощущению носителя языка, когда он слышит жёсткий акцент иммигранта.
Ладно, это личное, против кино ничего не имею, снято круто, наполнение годное. Настоятельно рекомендую тебе продолжать свою деятельность.

CityAceE
10.01.2024, 22:17
HardWareMan, я тебя отлично понимаю! Но для меня, к сожалению (или же к счастью), родные мнемоники i8080 ровным счётом ничего не значат. Скорее всего именно поэтому я так бесцеремонно, без угрызений совести, не только сам программирую, но и показываю остальным, как это делать в "неправильных" мнемониках Z80. Скорее всего это произошло из-за того, что когда Специалист был моим первым и единственным компьютером, я не умел программировать на ассемблере. У меня не было знакомых, которые могли бы меня чему-то научить. Единственным источником информации по Специалисту для меня были журналы Моделист-Конструктор. Ну и то, что я сам смог накопать, ковыряясь через Монитор в играх. А ассемблер в моей жизни появился позже, когда я обзавёлся Спектрумом. И мнемоника Z80 - это единственное, что на сегодня я знаю без справочников. Например, сейчас я могу на Python не пописать пару месяцев, а потом даже не вспомнить какой синтаксис у цикла. Я ассемблер ARM трижды с нуля учил, потому что делал перерыв и всё начисто забывал. А с Z80 всё иначе. Это первые знания, которые были получены в молодом возрасте на пике энтузиазма. Полагаю, что у тебя так с i8080, и мои методы, естественно, кажутся тебе кощунственными.

HardWareMan
11.01.2024, 06:51
CityAceE, ты, кстати, выводил надпись на спецтрумский манер (что логично, используя мнемоники Z80 - ФЬЮТЬ-ХА!). А ты выводи теперь по-Спецовски, 6х8. Я не советую тебе ковырять монитор, его вывод символа медленный из-за использования стека, но могу подкинуть часть своего BIOS. Если решишь использовать в своём новом кино - я не против.

b2m
11.01.2024, 13:27
Единственным источником информации по Специалисту для меня были журналы Моделист-Компьютер.
Ну да, конечно, Компьютер... :)

CityAceE
11.01.2024, 14:46
Ну да, конечно, Компьютер... :)
Оговорочка по Фрейду, как говорится :)

CityAceE
11.01.2024, 15:38
А ты выводи теперь по-Спецовски, 6х8.
Ну да, так было бы правильнее. Показать как это делается с помощью вызова процедуры из ПЗУ, а затем продемонстрировать реализацию этого метода с нуля. Однако в твоих же исходниках есть такой комментарий относительно процедуры вывода символа на экран:


; Вывод символа
; Самая муторная подпрограмма

Вот именно по этой причине я решил продемонстрировать создание процедуры печати со шрифтом, у которого ширина кратна байту. Но за базовые процедуры спасибо. Я их перевёл в понятную мне мнемонику и скомпилировал с помощью SJAsmPlus:

https://pic.maxiol.com/images2/1704976634.780858384.screen.png

Но, видимо, где-то ошибся при конвертировании, так как выше нижней строчки поднять текст никак не получается. Для вывода использую процедуру OutText, а координаты записываю в ячейки CurX и CurY.

ivagor
11.01.2024, 16:23
Ты пробовал CurY от 9 до 255?

HardWareMan
11.01.2024, 16:41
Ты пробовал CurY от 9 до 255?
Там 0:0 это левый верхний угол. И ЕМНИП координатная логика полностью повторяет мониторовскую. Всмысле, X это координата с шагом 2 точки, а Y - с шагом в 1 точку, но 0-7 эквивалентны 8. Сами ячейки должны быть в ОЗУ и инициироваться до вывода символа. Либо можно вставить код #0C перед текстом (или даже #1F). Первый просто отправит текст домой (в левый верхний угол), а второй при этом ещё и экран очистит.

- - - Добавлено - - -

PS В комментах может быть путаница, имейте в виду.

CityAceE
11.01.2024, 16:51
Ты пробовал CurY от 9 до 255?
Да, конечно. Я же посмотрел логику:


lda CurX ;
ani 0FCh ;
rrc ;
rrc ;
adi 90h ;
mov h,a ;
lda CurY ;
cpi 08h ;
jnc OutSymCrd ;
mvi a,08h ;
sta CurY ;
OutSymCrd: sui 08h ;
mov l,a ; [HL] верх координаты





ld a,(CurX) ;
and a,0FCh ;
rrca ;
rrca ;
add a,90h ;
ld h,a ;
ld a,(CurY) ;
cp a,08h ;
jp nc,OutSymCrd ;
ld a,08h ;
ld (CurY),a ;
OutSymCrd: sub a,08h ;
ld l,a ; [HL] верх координаты

ivagor
11.01.2024, 17:31
Есть некоторая ирония в том, что в данном случае камнем преткновения стали мнемоники z80 в сочетании с sjasm
OutSymCrd: sub a,08h ;
в sjasm компилируется в две команды, первая из которых всегда обнуляет А.

HardWareMan
11.01.2024, 19:02
ivagor, вот это было внезапно!

- - - Добавлено - - -

Погоди, а разве не просто "SUB 08H" должно быть?

SUB (HL) 96 1 NOP 1
SUB (IX*) 96DD 3 NOP 1
SUB (IY*) 96FD 3 NOP 1
SUB A 97 1 NOP 1
SUB B 90 1 NOP 1
SUB C 91 1 NOP 1
SUB D 92 1 NOP 1
SUB E 93 1 NOP 1
SUB H 94 1 NOP 1
SUB L 95 1 NOP 1
SUB * D6 2 NOP 1

- - - Добавлено - - -

А иначе он делает похоже:

SUB A
SUB 08H
И первое действительно обнулит А (А-А=0). Медвежья услуга ассемблера.

CityAceE
11.01.2024, 19:03
В общем, для перегона я воспользовался табличкой вот с таким синтаксисом:


SUB A,B
SUB A,C
SUB A,D
SUB A,E
SUB A,H
SUB A,L
SUB A,(HL)
SUB A,A
SUB A,d

Это же касается и всего остального. Пофиксил и перезалил исходник. Сейчас всё работает как задумано!

ivagor
12.01.2024, 08:07
Вот про преобразование мнемоник 8080->z80 мне было бы интересно посмотреть/послушать/почитать. Есть несколько конвертеров, но у каждого из них есть какие-то странности или ошибки, которые не позволяют мне нормально преобразовать большую программу. Собирался сделать подход к своему конвертеру, но так и не созрел.

CityAceE
12.01.2024, 10:08
Вот про преобразование мнемоник 8080->z80 мне было бы интересно посмотреть/послушать/почитать.
Я, к сожалению, ничего интересного рассказать не смогу. У меня это полуавтоматический процесс. Скрипт на Python "в лоб" меняет мнемоники, а потом ещё руками нужно проходится, так как скрипт самый элементарный без доли интеллекта.

ivagor
12.01.2024, 11:00
Поделишься скриптом? Интересно было бы посмотреть.

CityAceE
12.01.2024, 12:08
Поделишься скриптом?
Да там делиться-то особо нечем. Всё делается деревянно, "в лоб". Заготовка просто, которая ни регистр не учитывает, ни количество пробелов. Словарь, естественно, полностью заполнить нужно.


filename = "BIOS.ASM"

file = open(filename, 'r')

conv_dict ={
".db": "db",
".include": "include",
"push h": "push hl",
"push b": "push bc",
"lxi h,": "ld hl,",
"dad sp": "add hl,sp",
}

text = ""

for line in file:

for key in conv_dict.keys():
line = line.replace(key, str(conv_dict[key]))
text += line

with open(filename + ".txt", "w") as f:
f.write(text)

HardWareMan
12.01.2024, 13:48
CityAceE, ну вот, прикинь. А всё просто потому что у каждой мнемоники i8080 по сути есть автопроверка. Например, MOV это всегда 2 регистра, а MVI это регистр и число. Как когда-то в одном холиворном обсуждении этого на этом форуме кое-кто говорил: "это они сэкономили на программе ассемблера, заставляя программиста помнить!". Ну не знаю. Если программист говорит, что его надо заставлять, быть может это не его место в принципе? А автоконтроль лично мне позволял писать относительно большие программы в тетрадке, чтобы потом, дождавшись занятия на кружке, ввести её в комп и оно сразу заработало как надо, потому что читается программа вполне однозначно, в отличие от кучи одинаковых условных LD с разными операндами. Или вот, сквозь десятилетия, оно позволяет упростить скрипт преобразования условному CityAceE для конвертации на другой язык.

PS Скрипт преобразования на самом деле прост по алгоритму: достаточно сделать минимальный разбор каждой строки на 4 составляющие: МЕТКА + КОМАНДА + ОПЕРАНД + КОММЕНТАРИЙ. Просто меняешь потом связку КОМАНДА + ОПЕРАНД, если такие присутствуют, и собираешь строку обратно. И этому правилу будут соответствовать все строки текста ассемблерного текста.

ivagor
12.01.2024, 14:01
достаточно сделать минимальный разбор каждой строки на 4 составляющие: МЕТКА + КОМАНДА + ОПЕРАНД + КОММЕНТАРИЙ.
Так лучше не надо, в строке может быть несколько команд.

HardWareMan
12.01.2024, 14:33
Так лучше не надо, в строке может быть несколько команд.
В синтаксисе i8080 - нет.

NEO SPECTRUMAN
12.01.2024, 16:01
В синтаксисе i8080 - нет.
хош сказать что ТЫ перебрал все 8080 асмы на всех платформах?

mov b,d : mov c,e
нормальный синтаксис


да и вообще цепляние за ущербный 8080 асм
это чисто синдром уточки от любителей перфолент и ересь
только z80 подход единоправильный

"милионы" действущий програмистов на этом 8080 ****** (звездоочки)
и нижеплинтусное качество выходного кода в 90% случаев
этому подтверждение


что у каждой мнемоники i8080 по сути есть автопроверка.
отлишная отмазка
видимо "сквозная" компиляция с перфоленты
длитсо аж на 10% быстрее

это даже для самого 8080 не проблема чуть подробней разобрать строку
что за упертый нубизм

HardWareMan
12.01.2024, 16:32
О, вот и бугуртинг подъехал. Но пусть "z80 подход единоправильный" остаётся на этом самом вашем z80, ок?
https://i.postimg.cc/3RKmyc14/f61ec5d8df2a2cd833c0e8f84318eaab.jpg

Zidane
13.01.2024, 06:01
и опять скатываемся в шлак. Лично мне ассемблер i8080 куда как ближе. Четкое разделение на мнемоники и аргументы, без всякого множества кавычек. Но это лично мое мнение, равно как и каждый из здесь присутствующих имеет свое, по этому же вопросу. Спор лишен смысла и уж очень напоминает один рассказ, где предписывалось разбивать яйцо только с тупой стороны оного...

Но в целом - да. Я к спектруму стал терять интерес именно из-за его ассемблера. Для меня он, как тут кто-то написал - избыточен. Ну и организация экранной области и... да много чего.

fifan
13.01.2024, 14:43
Вечное противостояние любителей мнемоник 8080 и Z80. На этом форуме это уже было с десяток раз. Хватит мерится письками!

CityAceE
24.01.2024, 21:49
Продолжение эпопеи:


https://youtu.be/Y6WUOFEbFPY

Error404
24.01.2024, 22:34
CityAceE, ну вот, прикинь. А всё просто потому что у каждой мнемоники i8080 по сути есть автопроверка. Например, MOV это всегда 2 регистра, а MVI это регистр и число. Как когда-то в одном холиворном обсуждении этого на этом форуме кое-кто говорил: "это они сэкономили на программе ассемблера, заставляя программиста помнить!". Ну не знаю. Если программист говорит, что его надо заставлять, быть может это не его место в принципе?

Это говорил я, хотя и не программист. Можешь помериться теперь кто сколько напрограммировал, и засунуть свои давние воспоминания на самую дальнюю полочку. А задело, да? Знаешь почему? Потому что так оно и было.
И кстати, чего не говоришь на старославянском? Ровно тот же случай - древнючий язык времен слабой формализации мышления, не прошедший ни редукции ни индукции отчего набитый лишними слогами и буквами. Ну или на мойве :) Впрочем, все вы там скоро будете говорить на одном единственно правильном...

HardWareMan
25.01.2024, 06:57
Это говорил я, хотя и не программист. Можешь помериться теперь кто сколько напрограммировал, и засунуть свои давние воспоминания на самую дальнюю полочку.
Ну давай, померяй, только не в СНГ а во всём мире. Интересно, написал ли Гейтс лодыря для Альтаира в самолёте который бы с первого раза заработал, как того гласит байка, если бы Альтаир был на Z80 и его мнемониках?

А задело, да? Знаешь почему? Потому что так оно и было.
Пока по всем признакам задело лишь тебя, раз ты напомнил о себе спустя столько времени (пара лет точно). Я лишь привёл "чей-то" аргумент, специально его обезличил. Но ты, скорее всего, до сих пор кушать не можешь. Это всего лишь моё предположение и оно пока подтверждается конкретно твоим постом. Буду рад, если окажется что это не так.

И кстати, чего не говоришь на старославянском? Ровно тот же случай - древнючий язык времен слабой формализации мышления, не прошедший ни редукции ни индукции отчего набитый лишними слогами и буквами. Ну или на мойве :) Впрочем, все вы там скоро будете говорить на одном единственно правильном...
Я не знаю, про кого ты там говоришь, обобщая "все", за себя скажу лишь что я говорю ровно на том языке, которому меня научили родители и школа. Твоё навязывание всем своего "единственно правильного" (тм) мнения о многом говорит о тебе. Фу таким быть.

Trol73
25.01.2024, 11:54
А есть ли большой смысл во всех этих мнемониках в 2024 году, когда программы пишутся не в блокнотиках, а на производительных машинах с гигабайтами и гигагерцами?
Есть куча мнемоник MOV, MVI, LXI, LDA, STA, LDAX, STAX, LHLD, SHLD, смысл которых в выполнении операции присвоения, то почему бы не использовать вместо них очевидный синтаксис "X = Y"?
Аналогично и для кучи других арифметических инструкций.
Для человека такое, имхо, выглядит гораздо более читабельно, а современный компилятор без проблем разберёт.

Hunta
25.01.2024, 14:34
современный компилятор без проблем разберёт
Пример. Язык ассемблера MACRO-11. Штатный компилятор от производителя. Можно макросами сделать так:


PROCEDURE MULBLK
BEGIN
LET R0 := BLKBEG
LET R2 := CAPTR
LET R3 := ACTCNT

THRU R3 ; blocks count

; INIT
LET R4 := (R2) ; block words count
IF RESULT IS NE THEN
LET R5 := 2(R2) ; first word command pointer
THRU R4
LET (R0)+ := (R5)+ ; copy next block
END
ELSE
LET (R0)+ := #NOP
END

IF APHASE NE #0 THEN ; if not init calculating

; ACTION
LET R4 := 4(R2)
IF RESULT IS NE THEN
LET R5 := 6(R2) ; first word command pointer
THRU R4
LET (R0)+ := (R5)+ ; copy next block
END
END

END

END

LET (R0)+ := (PC) ; and return at end
RETURN
END MULBLK

ivagor
25.01.2024, 16:10
Можно макросами сделать так
Для 8080 примерно так можно делать с использованием PL/M 80, который скорее является надстройкой над ассемблером, чем ЯВУ.

fifan
25.01.2024, 16:24
Язык ассемблера MACRO-11.
Как-то не эстетично, это всё же не АВР или ПИК.

HardWareMan
25.01.2024, 16:31
Для 8080 примерно так можно делать с использованием PL/M 80, который скорее является надстройкой над ассемблером, чем ЯВУ.
Ну тот же MASM в своё время был/есть очень популярным. Там в итоговой программе родных мнемоник иногда почти и нет. Макросы тема хорошая, но использовать их надо с умом и осторожно. Что касается псевдоязыка, который предложил Trol73, то та же IDA, например, в него "декодирует" дизассемблированный текст. Вполне себе повышает читабельность логики кода. Так что тоже достаточно разумная идея для кроссплатформы.

Hunta
25.01.2024, 16:34
Как-то не эстетично
Зато удобно, быстро и практично.
По прикидкам, моя скорость написания программ выросла на порядок, а ещё, как оказалось - КРАЙНЕ ускоряет разборку в логике дизассемблированных программ - ну, правда, при условии, что код не был написан в стиле "крутое спагетти".

Trol73
25.01.2024, 17:13
Сейчас пишу компилятор С-- - подобного языка для 8080/8085. И заодно декомпилятор в него.
Хочется получить возможности ассемблера при Си-подобном синтаксисе.
Под спойлером - результат прогона декомпилятора для одного тетриса (tetris6.gam) под 86РК



extern proc biosReadKeyboard() absolute 0xF803
extern proc biosPrintChar(chr: C) absolute 0xF809
extern proc biosPrintMessage(msg: HL) absolute 0xF818
extern proc biosCheckKeyboard() absolute 0xF81B ; Ввод кода нажатой клавиши (A=0FFH - не нажата, A=0FEH - РУС/ЛАТ, ИНАЧЕ - код клавиши)
extern proc biosWarmBoot() absolute 0xF86C


var byte_1300: byte absolute 0x1300
var byte_1301: byte absolute 0x1301
var byte_1302: byte absolute 0x1302
var byte_1303: byte absolute 0x1303
var word_1305: word absolute 0x1305
var word_1307: word absolute 0x1307
var word_1309: word absolute 0x1309
var byte_130B: byte absolute 0x130B
var byte_130C: byte absolute 0x130C
var byte_130D: byte absolute 0x130D
var byte_130E: byte absolute 0x130E
var byte_130F: byte absolute 0x130F
var byte_1310: byte absolute 0x1310
var byte_1311: byte absolute 0x1311
var byte_1312: byte absolute 0x1312
var byte_1313: byte absolute 0x1313
var byte_1314: byte absolute 0x1314
var word_1315: word absolute 0x1315
var byte_1317: byte absolute 0x1317
var byte_1318: byte absolute 0x1318
var byte_1319: byte absolute 0x1319
var word_1320: word absolute 0x1320
var byte_1322: byte absolute 0x1322
var byte_1323: byte absolute 0x1323
var byte_1326: byte absolute 0x1326
var word_1327: word absolute 0x1327
var byte_1329: byte absolute 0x1329
var word_132A: word absolute 0x132A
var word_132C: word absolute 0x132C
var byte_132E: byte absolute 0x132E
var byte_132F: byte absolute 0x132F
var byte_1338: byte absolute 0x1338

proc start() {
SP = 0x75FF
DE = 0x03F6
CALL proc_0350
byte_132E = A = 0
BC = 0x100A
CALL proc_056F
word_1305 = HL = 0x0100
@proc_0019:
HL = 0x1330
JMP proc_079D
}

data_001F:
byte[] {
0x00, 0x4E, 0x00, 0x50, 0x00, 0x02, 0x00, 0x00, 0x00, 0x4E, 0x00, 0x50, 0x00, 0x02, 0x00, 0x00, 0x00, 0x4E, 0x00, 0x50, 0x00, 0x02, 0x00, 0x00, 0x00, 0x4E, 0x00, 0x50, 0x00, 0x02, 0x00, 0x00,
0x00, 0x04, 0x00, 0xFE, 0xFF, 0x02, 0x00, 0x00, 0x00, 0x9C, 0x00, 0xB2, 0xFF, 0x4E, 0x00, 0x00, 0x00, 0x04, 0x00, 0xFE, 0xFF, 0x02, 0x00, 0x00, 0x00, 0x9C, 0x00, 0xB2, 0xFF, 0x4E, 0x00, 0x00,
0x00, 0x4C, 0x00, 0x4E, 0x00, 0x02, 0x00, 0x00, 0x00, 0x50, 0x00, 0x02, 0x00, 0xB2, 0xFF, 0x00, 0x00, 0x4C, 0x00, 0x4E, 0x00, 0x02, 0x00, 0x00, 0x00, 0x50, 0x00, 0x02, 0x00, 0xB2, 0xFF, 0x00,
0x00, 0x50, 0x00, 0x4E, 0x00, 0xFE, 0xFF, 0x00, 0x00, 0x4C, 0x00, 0xFE, 0xFF, 0xB2, 0xFF, 0x00, 0x00, 0x50, 0x00, 0x4E, 0x00, 0xFE, 0xFF, 0x00, 0x00, 0x4C, 0x00, 0xFE, 0xFF, 0xB2, 0xFF, 0x00,
0x00, 0x4C, 0x00, 0x02, 0x00, 0xFE, 0xFF, 0x00, 0x00, 0x50, 0x00, 0x4E, 0x00, 0xB2, 0xFF, 0x00, 0x00, 0xFE, 0xFF, 0x02, 0x00, 0xB4, 0xFF, 0x00, 0x00, 0x4E, 0x00, 0xB0, 0xFF, 0xB2, 0xFF, 0x00,
0x00, 0x50, 0x00, 0xFE, 0xFF, 0x02, 0x00, 0x00, 0x00, 0x4E, 0x00, 0xB4, 0xFF, 0xB2, 0xFF, 0x00, 0x00, 0x02, 0x00, 0xFE, 0xFF, 0xB0, 0xFF, 0x00, 0x00, 0x4C, 0x00, 0x4E, 0x00, 0xB2, 0xFF, 0x00,
0x00, 0x4E, 0x00, 0xFE, 0xFF, 0x02, 0x00, 0x00, 0x00, 0x4E, 0x00, 0x02, 0x00, 0xB2, 0xFF, 0x00, 0x00, 0xFE, 0xFF, 0x02, 0x00, 0xB2, 0xFF, 0x00, 0x00, 0x4E, 0x00, 0xFE, 0xFF, 0xB2, 0xFF, 0x00,
0x00
}

proc proc_0100() {
word_1307 = HL = 0x7824
word_1309 = HL
XCHG
byte_1319 = A = 0x14
byte_1311 = A = 0
byte_1312 = A
CALL proc_021F
CALL proc_024A
byte_132F = A
CALL proc_021F
CALL proc_025E
A = byte_132F
CPI 0x2E
JNZ proc_032E
HL = 0x7ACE
BC = 0x0802
lbl_0133:
M = 0x20
HL++
B--
JNZ lbl_0133
B = 0x08
HL = 0x7B1C
C--
JNZ lbl_0133
A = byte_1317
A |= A
JNZ lbl_0153
DE = 0x7AD0
CALL proc_0228
CALL proc_025E
lbl_0153:
byte_130D = A = byte_130F
byte_130E = A = byte_1310
byte_130C = A = 0
lbl_0163:
HL = 0x130D
A++
CMP M
CZ proc_017B
HL = 0x130E
CMP M
CZ proc_02BF
C = 0xFF
lbl_0174:
C--
JNZ lbl_0174
JMP lbl_0163
}

proc proc_017B() {
PUSH PSW
M++
A = 0xFF
byte_130B = A
CALL biosCheckKeyboard
CPI 0xFF
JZ proc_02BD
B = A
HL = 0x130D
A = byte_130F
A += M
M = A
A = B
CPI 0x08
JZ proc_01E1
CPI 0x18
JZ proc_01EC
CPI 0x1A
JZ proc_01F7
CPI 0x19
JZ proc_0207
HL = word_1307
XCHG
CALL proc_021F
CALL proc_027F
lbl_01B2:
CALL proc_021F
HL = 0x004E
HL += DE
XCHG
A = byte_1319
A--
byte_1319 = A
CALL proc_024A
CPI 0x2E
JZ lbl_01B2
CALL proc_021F
HL = 0xFFB2
HL += DE
word_1307 = HL
XCHG
A = byte_1319
A++
byte_1319 = A
CALL proc_025E
JMP proc_02BD
}

proc proc_01E1() {
HL = word_1307
HL--
HL--
word_1309 = HL
JMP proc_028C
}

proc proc_01EC() {
HL = word_1307
HL++
HL++
word_1309 = HL
JMP proc_028C
}

proc proc_01F7() {
A = byte_1311
A++
CPI 0x04
JM lbl_0201
A = 0
lbl_0201:
byte_1312 = A
JMP proc_028C
}

proc proc_0207() {
CALL biosPrintChar(0x07)
A = byte_1317
A -= 0x04
byte_1317 = A
JZ proc_02BD
A = 0x04
byte_1317 = A
JMP proc_02BD
}

proc proc_021F() {
A = byte_1311
byte_1313 = A
JMP proc_0234
}

proc proc_0228() {
A = byte_1300
JMP proc_0237
}

proc proc_022E() {
A = byte_1312
byte_1313 = A
@proc_0234:
A = byte_1301
@proc_0237:
RRC
RRC
RRC
A &= 0xE0
C = A
A = byte_1313
RLC
RLC
RLC
A &= 0x1F
A += C
C = A
B = 0
RET
}

proc proc_024A() {
A = mem[BC]
L = A
C++
A = mem[BC]
H = A
C++
HL += DE
A = M
CPI 0x2E
RNZ
A = C
A &= 0x07
JNZ proc_024A
A = 0x2E
RET
}

proc proc_025E() {
byte_1302 = A = 0x17
byte_1303 = A = 0x11
@proc_0268:
L = A = mem[BC]
C++
H = A = mem[BC]
C++
HL += DE
M = A = byte_1302
HL++
M = A = byte_1303
A = C
A &= 0x07
JNZ proc_0268
RET
}

proc proc_027F() {
byte_1302 = A = 0x2E
byte_1303 = A = 0x20
JMP proc_0268
}

proc proc_028C() {
HL = word_1307
XCHG
CALL proc_021F
CALL proc_027F
HL = word_1309
XCHG
CALL proc_022E
CALL proc_024A
CPI 0x2E
JNZ lbl_02B3
XCHG
word_1307 = HL
byte_130B = A = 0
byte_1311 = A = byte_1312
lbl_02B3:
CALL proc_021F
HL = word_1307
XCHG
CALL proc_025E
@proc_02BD:
POP PSW
RET
}

proc proc_02BF() {
PUSH PSW
A = byte_1310
A += M
byte_130E = A
HL = word_1307
XCHG
HL = 0x004E
HL += DE
word_1309 = HL
CALL proc_021F
CALL proc_027F
HL = word_1309
XCHG
A = C
A -= 0x08
C = A
CALL proc_024A
CPI 0x2E
JNZ proc_02FB
XCHG
word_1307 = HL
A = byte_1319
A--
byte_1319 = A
@proc_02F3:
CALL proc_021F
CALL proc_025E
POP PSW
RET
}

proc proc_02FB() {
A = byte_130B
A |= A
JNZ proc_0316
@proc_0302:
HL = word_1307
XCHG
JMP proc_02F3
}

data_0309:
byte[] {
0x2A, 0x07, 0x13, 0xEB, 0xCD, 0x1F, 0x02, 0xCD, 0x7F, 0x02, 0xC3, 0xB3, 0x02
}

proc proc_0316() {
A = byte_130C
A |= A
JNZ proc_0324
A++
byte_130C = A
JMP proc_0302
}

proc proc_0324() {
HL = word_1307
XCHG
CALL proc_021F
CALL proc_025E
@proc_032E:
SP = 0x75FF
JMP proc_0836
}

proc proc_0334() {
HL = word_1305
C = 0x10
lbl_0339:
A = H
HL += HL
A &= 0x60
JPE lbl_0341
HL++
lbl_0341:
C--
JNZ lbl_0339
word_1305 = HL
A = H
A += L
A &= 0x07
JZ proc_0334
RET
}

proc proc_0350() {
C = 0x1F
PUSH DE
CALL biosPrintChar
POP DE
HL = 0x7997
B = 0x07
A = mem[DE]
DE++
byte_1318 = A
lbl_0361:
PUSH BC
BC = 0x0808
lbl_0365:
A = mem[DE]
DE++
PUSH DE
E = A
A = byte_1318
D = A
A = E
lbl_036E:
RAL
JNC lbl_0373
M = D
lbl_0373:
HL++
C--
JNZ lbl_036E
C = 0x08
POP DE
B--
JNZ lbl_0365
POP BC
B--
RZ
C = 0x0E
lbl_0384:
HL++
C--
JNZ lbl_0384
JMP lbl_0361
}

proc proc_038C() {
CALL biosPrintChar(0x1F)
D = 0x15
lbl_0393:
PUSH DE
CALL proc_0577
BC = 0x0B18
CALL proc_056F
POP DE
D--
JZ proc_03AD
PUSH DE
CALL biosPrintMessage(0x045D)
POP DE
JMP lbl_0393
}

proc proc_03AD() {
CALL biosPrintMessage(0x0474)
CALL biosPrintChar(0x0C)
RET
}

proc proc_03B9() {
HL = 0x7885
DE = 0x048B
CALL proc_03ED
HL = 0x791E
CALL proc_03ED
HL = 0x796C
CALL proc_03ED
HL = 0x79BA
CALL proc_03ED
HL = 0x7A08
CALL proc_03ED
HL = 0x7BDC
CALL proc_03ED
HL = 0x7C78
CALL proc_03ED
HL = 0x7D14
CALL proc_03ED
RET
}

proc proc_03ED() {
A = mem[DE]
DE++
A |= A
RZ
M = A
HL++
JMP proc_03ED
}

data_03F6:
byte[] {
0x40, 0x00, 0x78, 0xFE, 0x18, 0x42, 0x18, 0x42, 0x00, 0x00, 0x84, 0x10, 0x24, 0x44, 0x24, 0x42, 0x00, 0x00, 0x80, 0x10, 0x42, 0x48, 0x42, 0x42, 0x00, 0x00, 0x80, 0x10, 0x42, 0x70, 0x42, 0x7E,
0x00, 0x00, 0x80, 0x10, 0x7E, 0x48, 0x7E, 0x42, 0x00, 0x00, 0x84, 0x10, 0x42, 0x44, 0x42, 0x42, 0x00, 0x00, 0x78, 0x10, 0x42, 0x42, 0x42, 0x42, 0x00, 0x0D, 0x0A, 0x0A, 0x20, 0x20, 0x20, 0x20,
0x20, 0x77, 0x61, 0x7B, 0x65, 0x20, 0x69, 0x6D, 0x71, 0x20, 0x3F, 0x20, 0x00, 0x0D, 0x0A, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x77, 0x61, 0x7B, 0x20, 0x72, 0x61, 0x6E, 0x67, 0x20, 0x28, 0x30,
0x2D, 0x39, 0x29, 0x20, 0x3F, 0x20, 0x00, 0x11, 0x2E, 0x20, 0x2E, 0x20, 0x2E, 0x20, 0x2E, 0x20, 0x2E, 0x20, 0x2E, 0x20, 0x2E, 0x20, 0x2E, 0x20, 0x2E, 0x20, 0x2E, 0x20, 0x11, 0x00, 0x15, 0x14,
0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x11, 0x00, 0x75, 0x70, 0x72, 0x61, 0x77, 0x6C, 0x65, 0x6E, 0x69, 0x65, 0x00,
0x1D, 0x20, 0x2D, 0x20, 0x73, 0x64, 0x77, 0x69, 0x67, 0x20, 0x77, 0x6C, 0x65, 0x77, 0x6F, 0x00, 0x0E, 0x20, 0x2D, 0x20, 0x73, 0x64, 0x77, 0x69, 0x67, 0x20, 0x77, 0x70, 0x72, 0x61, 0x77, 0x6F,
0x00, 0x0F, 0x20, 0x2D, 0x20, 0x70, 0x6F, 0x77, 0x6F, 0x72, 0x6F, 0x74, 0x00, 0x0B, 0x20, 0x2D, 0x20, 0x70, 0x6F, 0x6B, 0x61, 0x7A, 0x61, 0x74, 0x78, 0x20, 0x73, 0x6C, 0x65, 0x64, 0x75, 0x60,
0x7D, 0x60, 0x60, 0x00, 0x77, 0x73, 0x65, 0x67, 0x6F, 0x20, 0x6F, 0x7E, 0x6B, 0x6F, 0x77, 0x20, 0x20, 0x2D, 0x00, 0x72, 0x61, 0x6E, 0x67, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x2D, 0x00, 0x70, 0x6F, 0x6C, 0x6E, 0x79, 0x68, 0x20, 0x73, 0x74, 0x72, 0x6F, 0x6B, 0x20, 0x2D, 0x00
}

proc proc_0507() {
HL = 0x7DE6
word_132A = HL
B = 0x14
@proc_050F:
C = 0x0A
lbl_0511:
A = M
CPI 0x2E
JZ proc_0526
HL++
HL++
C--
JNZ lbl_0511
CALL proc_0535
HL = word_132A
JMP proc_050F
}

proc proc_0526() {
DE = 0xFFB2
HL = word_132A
HL += DE
word_132A = HL
B--
JNZ proc_050F
RET
}

proc proc_0535() {
PUSH BC
A = byte_1314
A++
byte_1314 = A
HL = word_132A
word_132C = HL
B--
lbl_0544:
C = 0x14
HL = word_132C
XCHG
HL = 0xFFB2
HL += DE
word_132C = HL
lbl_0551:
A = M
mem[DE] = A
DE++
HL++
C--
JNZ lbl_0551
B--
JNZ lbl_0544
HL = word_132C
DE = 0x2E20
C = 0x0A
lbl_0565:
M = D
HL++
M = E
HL++
C--
JNZ lbl_0565
POP BC
RET
}

proc proc_056F() {
CALL biosPrintChar
B--
JNZ proc_056F
RET
}

proc proc_0577() {
CALL biosPrintChar(0x0A)
JMP biosPrintChar(0x0D)
}

proc proc_0581() {
A = byte_1314
A++
B = A
A = byte_1338
A++
C = A
A = 0
lbl_058C:
A += 0x0A
C--
JNZ lbl_058C
CMP B
RP
A = byte_1338
CPI 0x09
RZ
A++
byte_1338 = A
JMP biosPrintChar(0x07)
}

proc proc_05A3() {
A = byte_1319
HL = 0x1338
A += M
A += M
A += M
HL = 0x1317
A += M
E = A
D = 0
HL = word_1315
HL += DE
word_1315 = HL
RET
}

proc proc_05BB() {
word_1327 = HL
XCHG
byte_1326 = A = 0
byte_1329 = A = H
lbl_05C7:
E = 0
B = 0x10
A |= A
lbl_05CC:
A = L
RAL
L = A
A = H
RAL
H = A
A = E
RAL
E = A
A -= 0x0A
CMC
JNC lbl_05DC
E = A
lbl_05DC:
B--
JNZ lbl_05CC
RAL
A &= 0x01
HL += HL
A |= L
L = A
A = E
A += 0x30
CALL proc_05FE
A = H
A |= L
JNZ lbl_05C7
A = byte_1329
A |= A
JP lbl_05FD
A = 0x2D
CALL proc_05FE
lbl_05FD:
RET
}

proc proc_05FE() {
PUSH HL
C = A
HL = word_1327
D = H
E = L
HL++
word_1327 = HL
A = byte_1326
A |= A
JZ lbl_061B
B = A
lbl_0611:
XCHG
A = M
XCHG
M = A
HL--
DE--
B--
JNZ lbl_0611
lbl_061B:
M = A = C
A = byte_1326
A++
byte_1326 = A
HL--
M = A
POP HL
RET
}

proc proc_0628() {
B = M
HL++
lbl_062A:
A = M
mem[DE] = A
HL++
DE++
B--
JNZ lbl_062A
RET
}

proc proc_0633() {
HL = 0x1330
B = 0x08
@proc_0638:
PUSH HL
@proc_0639:
CALL biosReadKeyboard()
C = A
CPI 0x08
JZ proc_0657
CPI 0x0D
JZ proc_0666
CPI 0x20
JM proc_0639
CALL biosPrintChar
POP HL
M = C
HL++
B--
JNZ proc_0638
RET
}

proc proc_0657() {
A = B
CPI 0x08
JP proc_0639
CALL biosPrintChar
POP HL
HL--
B++
JMP proc_0638
}

proc proc_0666() {
POP HL
lbl_0667:
M = 0x20
HL++
B--
JNZ lbl_0667
RET
}

proc proc_066F() {
HL = 0x1000
A = byte_132E
A++
E = A
D = 0x01
@proc_0679:
A = D
CPI 0x0A
JP proc_06D2
C = 0x20
A += 0x30
B = A
@proc_0684:
CALL proc_078A
C = B
CALL proc_078A
C = 0x2E
CALL proc_078A
CALL proc_0788
B = 0x08
CALL proc_077E
CALL proc_0792
A = M
HL++
A += 0x30
C = A
CALL proc_078A
CALL proc_0792
B = 0x06
HL++
CALL proc_077E
CALL proc_0792
BC = 0x0308
CALL proc_0795
A = byte_1322
CMP D
JNZ lbl_06C4
C = 0x2A
CALL proc_078A
CALL proc_078A
lbl_06C4:
D++
A = D
CMP E
RP
PUSH HL
PUSH DE
CALL proc_0577
POP DE
POP HL
JMP proc_0679
}

proc proc_06D2() {
C = 0x31
A += 0x26
B = A
JMP proc_0684
}

proc proc_06DA() {
A = byte_132E
A |= A
JNZ proc_06EE
A++
byte_132E = A
DE = 0x1000
HL = 0x1330
JMP proc_0773
}

proc proc_06EE() {
B = A
B++
C = 0
@proc_06F2:
DE = 0x1339
HL = 0x1000
A = C
RLC
RLC
RLC
RLC
A += 0x09
L = A
A = mem[DE]
CMP M
JZ proc_072E
JM proc_073C
@proc_0708:
A = L
A &= 0xF0
L = A
word_1320 = HL
A = C
A++
byte_1322 = A
CALL proc_0760
HL = word_1320
XCHG
@proc_071B:
HL = 0x1330
B = 0x10
CALL proc_0775
A = byte_132E
CPI 0x0F
RZ
A++
byte_132E = A
RET
}

proc proc_072E() {
A = M
@proc_072F:
HL++
DE++
byte_1323 = A
A = mem[DE]
CMP M
JZ proc_0756
JP proc_0708
@proc_073C:
C++
A = B
CMP C
JNZ proc_06F2
C--
A = byte_132E
CPI 0x0F
JNZ proc_0708
DE = 0x10E0
A = 0x0F
byte_1322 = A
JMP proc_071B
}

proc proc_0756() {
A = byte_1323
A--
JNZ proc_072F
JMP proc_073C
}

proc proc_0760() {
HL = 0x10EF
DE = 0x10FF
lbl_0766:
A = M
mem[DE] = A
HL--
DE--
A = word_1320
A--
CMP L
JNZ lbl_0766
RET
}

proc proc_0773() {
B = 0x10
@proc_0775:
A = M
mem[DE] = A
HL++
DE++
B--
JNZ proc_0775
RET
}

proc proc_077E() {
C = M
HL++
CALL proc_078A
B--
JNZ proc_077E
RET
}

proc proc_0788() {
C = 0x20
@proc_078A:
PUSH HL
PUSH DE
CALL biosPrintChar
POP DE
POP HL
RET
}

proc proc_0792() {
BC = 0x0520
@proc_0795:
PUSH HL
PUSH DE
CALL proc_056F
POP DE
POP HL
RET
}

proc proc_079D() {
BC = 0x1020
lbl_07A0:
M = C
HL++
B--
JNZ lbl_07A0
CALL biosPrintMessage(0x042F)
CALL proc_0633
CALL biosPrintMessage(0x0443)
lbl_07B5:
CALL biosReadKeyboard()
C = A
A -= 0x30
JM lbl_07B5
CPI 0x0A
JP lbl_07B5
byte_1338 = A
CALL proc_038C
word_1315 = HL = 0
byte_1314 = A = 0
byte_1317 = A = 0x04
CALL proc_03B9
CALL proc_0334
byte_1300 = A
@proc_07E1:
A = byte_1338
HL = 0x7C88
A += 0x30
M = A
HL = 0x131A
E = A = byte_1314
D = 0
CALL proc_05BB
HL = 0x131A
DE = 0x7D24
CALL proc_0628
DE = 0x1339
HL = word_1315
XCHG
CALL proc_05BB
HL = 0x1339
DE = 0x7BEC
CALL proc_0628
byte_1301 = A = byte_1300
CALL proc_0334
byte_1300 = A
A = 0x5A
HL = 0x1338
A -= M
A -= M
A -= M
A -= M
A -= M
A -= M
byte_1310 = A
A = 0x50
A -= M
A -= M
byte_130F = A
JMP proc_0100
}

proc proc_0836() {
CALL proc_0507
CALL proc_0581
CALL proc_05A3
A = byte_132F
CPI 0x2E
JZ proc_07E1
CALL proc_06DA
CALL biosPrintMessage(0x0882)
CALL proc_0577
CALL proc_066F
CALL biosPrintMessage(0x086E)
lbl_085C:
CALL biosReadKeyboard()
A &= 0x5F
CPI 0x44
JZ proc_0019
CPI 0x4E
JZ biosWarmBoot
JMP lbl_085C
}

data_086E:
byte[] {
0x1B, 0x59, 0x34, 0x25, 0x65, 0x7D, 0x65, 0x20, 0x72, 0x61, 0x7A, 0x20, 0x28, 0x44, 0x2F, 0x4E, 0x29, 0x20, 0x3F, 0x00, 0x1F, 0x0A, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x69, 0x6D, 0x71,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x72, 0x61, 0x6E, 0x67, 0x20, 0x20, 0x20, 0x20, 0x6F, 0x7E, 0x6B, 0x69, 0x0D, 0x0A, 0x00, 0xCA, 0x62, 0x03, 0x79, 0xBA, 0xCA, 0x0B, 0x03, 0x78, 0xA3, 0xBA,
0xC2, 0x36, 0x03, 0x3E, 0x23, 0x32, 0x5A, 0x03, 0xC3, 0x55, 0x03, 0xBB, 0xC2, 0x42, 0x03, 0x3E, 0x2B, 0x32, 0x5A, 0x03, 0xC3, 0x55, 0x03, 0xFE, 0x40, 0xC2, 0x4D, 0x03, 0x11, 0xB2, 0xFF, 0xC3,
0x50, 0x03, 0x11, 0x4E, 0x00, 0x3E, 0x19, 0x32, 0x5A, 0x03, 0x78, 0xE6, 0x3F, 0x47, 0x71, 0x23, 0x05, 0xC2, 0xE0, 0x01, 0xC3, 0x0B, 0x03, 0xC9, 0x00, 0x00, 0x00, 0xC9, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x02, 0x03, 0x03, 0x2E, 0x14, 0x02, 0x20, 0x81, 0x03, 0x01, 0x05, 0x01, 0x10, 0x81, 0x02
}

CityAceE
29.01.2024, 20:33
Оживляем игровой фон:

https://youtu.be/SXhXJeEr1hc

CityAceE
05.02.2024, 21:13
Печатаем спрайт с маской:


https://youtu.be/6MBNkv5w4fM

CityAceE
07.02.2024, 20:30
Коротенькая работа над ошибками. Спасибо ivagor'у!


https://youtu.be/sarmMa6DE0Q?si=GMQApykrErNg-8OC

ivagor
07.02.2024, 21:18
Еще раз присоединюсь к svofski, что это мелочи, на которые не стоит обращать много внимания, пока они не станут критичными. Лучше бы я пока помолчал, но теперь могу только учесть на будущее.
У меня еще вопрос, который возможно ты затрагивал в первых видео, которые я, признаюсь, подробно не смотрел. Почему не взял за основу какой-нибудь спековский игровой движок? Понятно, что современные движки сложные, зато их авторы теоретически могли помочь разобраться и упростить. Хотя конечно они (авторы движков) люди занятые и могли отказаться, тогда вопросов нет.

CityAceE
08.02.2024, 09:12
Еще раз присоединюсь к svofski, что это мелочи, на которые не стоит обращать много внимания, пока они не станут критичными. Лучше бы я пока помолчал, но теперь могу только учесть на будущее.
Вот как раз момент с OR/XOR (HL) не является мелочью, а является наглядным примером того, как можно одновременно сократить размер, сделать быстрее и понятнее код. Именно поэтому я решил снять короткий ролик. А другие ошибки типа опечаток я просто правлю тихонько за кадром. Но здесь был не тот случай! А я ещё как раз сидел и думал, как бы избавиться от PUSH/POP BC в этой процедуре. Нутром чуял, что можно, но в итоге так и забыл про (HL).


У меня еще вопрос, который возможно ты затрагивал в первых видео, которые я, признаюсь, подробно не смотрел. Почему не взял за основу какой-нибудь спековский игровой движок? Понятно, что современные движки сложные, зато их авторы теоретически могли помочь разобраться и упростить. Хотя конечно они (авторы движков) люди занятые и могли отказаться, тогда вопросов нет.
Нет, я этот вопрос не освещал. Основная причина, конечно, потому что я не игродел и у меня попросту таких знаний нет. У меня вообще изначально была идея просто показать как настроить среду и написать "Hello, World!" без процедур ПЗУ. Но когда увидел некоторый интерес со стороны зрителей, решил двинуться чуть дальше, а потом ещё и т.д.

Ну а что касается того, о чём я рассказываю, то я-то как раз по сути и описываю движок Sanchez'а! Как-то давно в разговоре он упомянул (когда это ещё не было широко известно), что для своих игр он вначале пишет прототип на C#, а графику в прототипе отрисовывает, записывая данные сразу в битмап. Мне это показалось очень интересным и я на Python сделал нечто вроде виртуального Спектрума со стандартной структурой Спектрумовского экрана, для которого можно писать на Python. А потом под это дело на Python решил сделать движок, чтобы потом перенести его на Спектрум, как это делал Sanchez. И так как у меня не было опыта создания спрайтовых игр, я начал одолевать Sanchez'а вопросами: "А как ты сделал то?", "А как ты реализовал это?". И Саша терпеливо на пальцах начал рассказывать мне как работает его движок, как он хранит карту, как анимирует тайлы, как выводит спрайты, как их сдвигает, а при необходимости ещё и разворачивает. Ко всему этому он шел постепенно, а мне просто выдал уже готовый результат. Например, когда-то ранее он мне рассказывал, как jerri на страницах этого форума подсказал ему крутую идею про вывод спрайта с маской по OR/XOR. Для меня это тогда вообще было тёмным лесом. Даже потом нашёл то сообщение на форуме, но всё равно ничего не понял. А вот когда я уже начал сам реализовывать печать спрайтов, то реально поразился красоте решения. Вот так по описаниям Sanchez'а я и написал по сути его движок на Python, обильно снабдив для себя комментариями. А сейчас я просто перекладываю его с Python на ассемблер, как и планировал ранее, только уже не для Спектрума и Z80, а для Специалиста и i8080. И, соответственно, сталкиваюсь с ограничениями в виде меньшего набора регистров у процессора, и отсутствия возможности синхронизировать вывод на экран. С последним у меня сейчас на Специалисте вообще проблема - анимированный спрайт героя сильно мерцает при восстановлении фона под ним. На Специалисте нужно делать дополнительный промежуточный буфер, что усложняет программу и понимание её работы. Я пока не реализовал это и вообще не уверен, что это легко позволит избавиться от мерцания. Хотя помочь, конечно, должно, потому что именно так сделано в Batty, в там на Специалисте уже ничего не мерцает. А вот на Спектруме нужно просто подгадать правильное по времени начало отрисовки без всяких лишних буферов и дополнительных процедур.

HardWareMan
08.02.2024, 09:43
...jerri на страницах этого форума подсказал ему крутую идею про вывод спрайта с маской по OR/XOR.
А чем она выгоднее метода AND/OR? При этом, во втором виде спрайты хранятся в прямом виде.

- - - Добавлено - - -

XOR используется в играх типа Lode Runner, чтобы повторным XOR по старым координатам восстановить оригинальную графику. Но если ты используешь маску, то ты явно портишь фон, отсюда и мой вопрос.

CityAceE
08.02.2024, 09:46
А чем она выгоднее метода AND/OR?
Я уже не вспомню сейчас. Возможно, из-за удобства сдвига по горизонтали или ещё чего-то. Но тогда я точно оценил красоту решения. Пока же действительно ничем не лучше, и даже хуже - нужно инвертировать сам спрайт.

HardWareMan
08.02.2024, 09:51
Я уже не вспомню сейчас. Возможно, из-за удобства сдвига по горизонтали или ещё чего-то. Но тогда я точно оценил красоту решения. Пока же действительно ничем не лучше, и даже хуже - нужно инвертировать сам спрайт.
Дык, если ты решил использовать координаты не по модулю 8 тебе и так и так сдвигать как маску так и спрайт (ну или заготавливать сдвинутые спрайты с масками). Так что не аргумент.

CityAceE
08.02.2024, 10:00
Санчез самоустранилася с форума, но, возможно, jerri вспомнит в чём профит.

ivagor
08.02.2024, 10:24
анимированный спрайт героя сильно мерцает при восстановлении фона под ним. На Специалисте нужно делать дополнительный промежуточный буфер, что усложняет программу и понимание её работы. Я пока не реализовал это и вообще не уверен, что это легко позволит избавиться от мерцания.
Промежуточный буфер точно поможет. Другое дело, что организовать этот буфер можно разными способами и тут как раз помог бы пример спековских движков.
OR+XOR выгоднее AND+(X)OR если для сдвига маски используется dad h. При этом "новые" крайние биты будут нулевые, а при сдвиге маски варианта AND+(X)OR они д.б. единичные.

HardWareMan
08.02.2024, 16:53
Вот это я и хотел услышать. Действительно, маска для XOR выгоднее для сдвига влево, чем маска для AND. Спасибо.

jerri
08.02.2024, 22:09
Санчез самоустранилася с форума, но, возможно, jerri вспомнит в чём профит.

Основной профит OR/XOR- если скроллим влево например спрайт шириной 16 точек
то удобно использовать add hl hl rla и спрайт будет в AHL
также если скроллить через таблицу, то одну и туже таблицу можно использовать для спрайта и маски.

- - - Добавлено - - -


Вот как раз момент с OR/XOR (HL) не является мелочью, а является наглядным примером того, как можно одновременно сократить размер, сделать быстрее и понятнее код. Именно поэтому я решил снять короткий ролик. А другие ошибки типа опечаток я просто правлю тихонько за кадром. Но здесь был не тот случай! А я ещё как раз сидел и думал, как бы избавиться от PUSH/POP BC в этой процедуре. Нутром чуял, что можно, но в итоге так и забыл про (HL).


С последним у меня сейчас на Специалисте вообще проблема - анимированный спрайт героя сильно мерцает при восстановлении фона под ним. На Специалисте нужно делать дополнительный промежуточный буфер, что усложняет программу и понимание её работы. Я пока не реализовал это и вообще не уверен, что это легко позволит избавиться от мерцания.

я предлагаю делать частичную буферизацию изображения.

CityAceE
09.02.2024, 11:04
также если скроллить через таблицу, то одну и туже таблицу можно использовать для спрайта и маски.


Вот! Это оно и есть! Сдвиг спрайтов с одновременным переворотом в этом движке производится при помощи одной таблицы на 4 кб (2 * 8 * 256).


я предлагаю делать частичную буферизацию изображения.
Так и планирую сделать.

CityAceE
12.02.2024, 17:43
Перемещаем спрайт с помощью клавиатуры:


https://youtu.be/eQe1Uf5TSvw

CityAceE
14.02.2024, 19:42
Восстанавливаем фон под спрайтом и анимируем сам спрайт:


https://youtu.be/pQJ7o1Zgdxw

Спрайт ожидаемо мерцает. Нужно делать дополнительный буфер, в котором готовить бутерброд из фона и спрайта и потом целиком рисовать его на экране. А перед этим нужно будет локально запретить восстанавливать анимацию, если она есть в этом месте. Всё это сильно усложняет логику и понимание. Может что-то предложите попроще?

parallelno
16.02.2024, 02:04
Я не вижу простых решений без полноэкранного бэкбуфера к сожалению.

HardWareMan
16.02.2024, 07:11
Я не вижу простых решений без полноэкранного бэкбуфера к сожалению.
Учитывая, что у него фон тайловый, то полноэкранный буфер не нужен - блиттинг последнего будет самым большим тормозом для специалиста. Достаточно иметь один буфер размером 2х2 тайла (при учёте размера спрайта равным одному тайлу), куда восстанавливать тайлы фона по карте от координаты спрайта. А потом блиттить этот кусок в экран. Хотя, лучше даже 3х3 тайла, тогда не нужно будет заботиться об восстановлении фона под старым спрайтом. Короче, это всё рассчитывается без проблем.

ivagor
16.02.2024, 10:06
Полноэкранный теневой буфер обязателен, но можно не графический, а тайловый. А графический буфер для впечатывания спрайта я в итоге (уже после urok7rom06c) сделал 32x256 точек. Минимально можно было 24x24, но тогда слишком сложно, 32x32 проще (ровно 2x2 фоновых тайла), а 32x256 (из них используется только фрагмент 32x32) совсем просто.

CityAceE
16.02.2024, 10:35
32x32 проще (ровно 2x2 фоновых тайла)
Вот я именно так и пытаюсь реализовать. Но это для дискретности перемещения в 8 пикселей. Для попиксельного перемещения нужно будет делать 48x48.

ivagor
16.02.2024, 11:05
Для попиксельного перемещения нужно будет делать 48x48.
Памяти свободной много, для простоты можно и 48x256 сделать (т.е. 6 экранных столбцов). А потом, если памяти не будет хватать, можно и переделать на 48x48.
Дополню, что и полноэкранный тайловый буфер (map_copy) не строго обязателен, можно вместо него список, но при наличии спрайтов со списком сложнее.

CityAceE
16.02.2024, 11:10
Памяти свободной много
Это пока ещё много. Там будет ещё две таблицы по 4К для пиксельного сдвига и одновременного разворота спрайта.

CityAceE
22.02.2024, 21:42
Избавляемся от мерцания спрайта путём организации теневого буфера:


https://youtu.be/LmWeN1as7B8

CityAceE
01.03.2024, 20:34
В этом ролике разобрал как обрабатывать столкновение с препятствиями:


https://youtu.be/etUUeq6EygI

tihsasha
22.04.2024, 10:44
Уроки 1..9 Станислава в мнемонике 580ВМ80. Используется компилятор TASM. Так как TASM не понимает incbin, то пришлось на Delphi сделать программу конвертации bin2asm.

AlexBel
22.04.2024, 11:42
Уроки 1..9 Станислава в мнемонике 580ВМ80. Используется компилятор TASM. Так как TASM не понимает incbin, то пришлось на Delphi сделать программу конвертации bin2asm.

Аналогично, только писал на Си :)