PDA

Просмотр полной версии : Программирование на Z80 в ассемблере и машинном коде на 48 Kb машине!



alex8418
21.01.2023, 23:20
Под руками лежит 48 Kb Ленинград (можно c прошивкой Turbo-91), программы Gens и Mons (в ней Я и сам работать не умею) и распечатаны все выпуски журнала ZX Ревю (возможно в плохом качестве, но вообщем-то это не так важно, хотя влияет на работоспособность программ - если что найдем правильное решение методом подбора)!

Да между прочим для Меня осталась загадкой возможность программирования в машинном коде в области 128 Kb компьютера Пентагон, так как операторы POKE и PEEK как Я понял работают в области 48 килобайт, хотя Я могу ошибаться, но про программирование в машинных кодах в области 128 килобайт никакой литературы найдено не было...

goodboy
21.01.2023, 23:47
про программирование в машинных кодах в области 128 килобайт никакой литературы найдено не было...
часть памяти подменяется другой, обычно это называется страницей

drbars
22.01.2023, 08:24
помню-помню такую конфигурацию) мне лет 12 было)

кстати, GENS так-то норм для супер начального уровня) У него каждая строка, помню, нумеровалась как в бейсике.

Destr
22.01.2023, 10:38
для супер начального уровня
Для супер начального уровня imho лучше ZEUS (удобней)
А нумерация строк вообще необязательно...

alex8418
22.01.2023, 20:48
часть памяти подменяется другой, обычно это называется страницей

Доброго времени суток goodboy! Напишите если возможно, конкретный пример с оператором POKE, чтобы всем читателям темы было понятно как работать в области 128 килобайт!

goodboy
22.01.2023, 21:10
как работать в области 128 килобайт!
диапазон адресов тот-же #0000-#FFFF, но 16к #C000-#FFFF можно подменять другим куском памяти.
сами страницы переключаются через порт (командой OUT)

Bedazzle
23.01.2023, 01:44
чтобы всем читателям темы было понятно как работать в области 128 килобайт!

Можно посмотреть бейсик-загрузчики игр для 128К.
Там будут примеры, как подменять память.
Ну, или можно нагуглить например, https://zxpress.ru/article.php?id=9971

0xDEAD
24.01.2023, 00:47
А я так вообще не могу понять, при чём здесь PEEK и POKE, когда речь идёт о программировании на ассемблере в машинных кодах (хоть и это звучит несколько дико).

Barmaley_m
24.01.2023, 23:28
Чтобы через POKE и PEEK был доступ к 128К памяти, нужно:

1) Сделать CLEAR 49151, чтобы переместить машинный стек ниже области страниц (49152-65535). В противном случае бейсик сразу подвиснет при попытке переключить страницу
2) Командами OUT 32765, 16+n, где n - номер страницы от 0 до 7, можно подключать по адресам 49152-65535 нужные страницы памяти по 16Кб каждая. Всего таким образом и получается 128Кб
3) Командами POKE и PEEK по адресам 49152-65535 можно, соответственно, просматривать и изменять эту память
4) Содержимое страницы 2 отображается на адреса памяти 32768-49151
5) Содержимое страницы 5 отображается на адреса памяти 16384-32767
Как-то так.

alex8418
25.01.2023, 01:56
Чтобы через POKE и PEEK был доступ к 128К памяти, нужно:

1) Сделать CLEAR 49151, чтобы переместить машинный стек ниже области страниц (49152-65535). В противном случае бейсик сразу подвиснет при попытке переключить страницу
2) Командами OUT 32765, 16+n, где n - номер страницы от 0 до 7, можно подключать по адресам 49152-65535 нужные страницы памяти по 16Кб каждая. Всего таким образом и получается 128Кб
3) Командами POKE и PEEK по адресам 49152-65535 можно, соответственно, просматривать и изменять эту память
4) Содержимое страницы 2 отображается на адреса памяти 32768-49151
5) Содержимое страницы 5 отображается на адреса памяти 16384-32767
Как-то так.

Соболезную по погибшим мирным жителям 14 января 2023 года в городе Днепр, надеюсь на скорейшее установление мира между Нашими государствами! Спасибо Barmaley_m за ответ попробуем реализовать, правда пользователь Bedazzle выложил ссылку в которой оператор OUT 32765 применяется, без цифры 16 после запятой - надо разобраться кто прав! Я так понимаю, что РОКЕ и PEEK в данном случае нужно применять в режиме BASIC 128 ?

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


А я так вообще не могу понять, при чём здесь PEEK и POKE, когда речь идёт о программировании на ассемблере в машинных кодах (хоть и это звучит несколько дико).

0xDEAD неправильно перефразировали в ассемблере и машинном коде (будет разбираться программирование и в ассемблере и в машинном коде)! Если Вы программировали в машинном коде, то Ваше возмущение насчёт POKE и PEEK не понятно?

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


Можно посмотреть бейсик-загрузчики игр для 128К.
Там будут примеры, как подменять память.
Ну, или можно нагуглить например, https://zxpress.ru/article.php?id=9971

Спасибо за ответ Bedazzle! Теперь бы разобраться, какой из ответов правильный? Может после всех ответов, у меня наконец появиться время заняться основной работой по теме, а именно написанием примеров программ и по возможности объяснением принципа их работы!

0xDEAD
25.01.2023, 02:01
Если Вы программировали в машинном коде, то Ваше возмущение насчёт POKE и PEEK не понятно?
Не знаю, откуда появилась мысль про "возмущение", но мне все-таки кажется, что PEEK и POKE - это команды BASIC, а не ассемблера. Или ошибаюсь?
А смысл набивать бейсик вручную опкодами ассемблера, если сам ассемблер это и так делает автоматически - тоже с трудом понимаю.

alex8418
25.01.2023, 02:24
диапазон адресов тот-же #0000-#FFFF, но 16к #C000-#FFFF можно подменять другим куском памяти.
сами страницы переключаются через порт (командой OUT)

Спасибо goodboy, диапазон #0000-#FFFF можно было представить в десятичном виде, потому что я думаю не все читатели статьи пока понимают, что FFFF в десятичном представлении это 65535, между прочим создатели журнала ZX Ревю тоже частенько упускали этот момент, возможно для экономии бумаги - предполагая что читатель читал все номера журнала и сориентируется. Я честно говоря сам долго догонял - вот статья с программой, в конце табличка с программой, а что с табличкой делать не понятно, так она ещё и в шестнадцатеричном виде представлена, перерыв весь журнал понял потом и даже разобрался в структуре написание программы в машинном коде! Правда об этом Я хотел позднее написать!

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


Не знаю, откуда появилась мысль про "возмущение", но мне все-таки кажется, что PEEK и POKE - это команды BASIC, а не ассемблера. Или ошибаюсь?
А смысл набивать бейсик вручную опкодами ассемблера, если сам ассемблер это и так делает автоматически - тоже с трудом понимаю.

Дело в том, что уважаемый 0xDEAD, что программы в машинном коде и ассемблере отличаются - это первое! Второе: Ассемблер - это программа имеющая, доступ не ко всем командам процессора, а вот машинный код - совсем другое дело, даёт полный доступ абсолютно ко всем командам процессора, которые представлены в соответствующей литературе, описывающей команды процессора Z80! Как Вы ещё получите доступ к машинному коду, если не через POKE и PEEK?

LW
25.01.2023, 02:32
диапазон #0000-#FFFF можно было представить в десятичном виде, потому что я думаю не все читатели статьи пока понимают, что FFFF в десятичном представлении это 65535
Лучше учитесь читать в шестнадцатеричном виде числа, понятнее будет всё в дальнейшем.

что программы в машинном коде и ассемблере отличаются - это первое!
А любопытно чем они отличаются?

Второе: Ассемблер - это программа
Ассемблер это не программа, это представление команд процессора в виде, доступном(более понятном) для чтения человеком.
А то, что вы называете ассемблером, это всего навсего компилятор, да и то, актуальные версии компиляторов, как правило, понимают недокументированные команды процессора

0xDEAD
25.01.2023, 03:22
Ассемблер - это программа имеющая, доступ не ко всем командам процессора, а вот машинный код - совсем другое дело
Да?
Понимаю, понимаю...

Barmaley_m
25.01.2023, 03:23
правда пользователь Bedazzle выложил ссылку в которой оператор OUT 32765 применяется, без цифры 16 после запятой - надо разобраться кто прав!
Цифра 16 - это бит 4 значения, которое идет в порт. Этот бит переключает ПЗУ бейсика 48 или 128 (0 - 128, 1 - 48). Поскольку команда OUT реализована именно в 48м бейсике, то вывод в порт значений, где бит 4 равен нулю, подключит вместо 48го, который должен был остаться, 128й бейсик в неожиданном месте исполнения программы. В результате произойдет сбой.

Я так понимаю, что РОКЕ и PEEK в данном случае нужно применять в режиме BASIC 128 ?
Можно 128, а можно (и лучше) набрать команду usr0 из 128го бейсика. В результате попадаешь в 48й, но 128К ОЗУ при этом не заблокировано (оно блокируется, если перейти в 48й бейсик из главного меню).

(будет разбираться программирование и в ассемблере и в машинном коде)!
Программирование (не отладка/анализ существующих программ, а составление новых!) в машинном коде сродни особо тяжелой форме мазохизма. Этим можно заняться, составляя какие-нибудь ооочень коротенькие программы на десяток команд, чтобы развлечься и получить развитие. Но для практической цели, т.е. для составления сколько-нибудь сложных и полезных программ или игр, совершенно бессмысленно. Если уж программировать на Спектруме - то на ассемблере.

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

Dart Alver
26.01.2023, 04:24
Ассемблер - это программа имеющая, доступ не ко всем командам процессора, а вот машинный код - совсем другое дело, даёт полный доступ абсолютно ко всем командам процессора, которые представлены в соответствующей литературе, описывающей команды процессора Z80!

Неожиданно вся соответствующая литература описывает команды процессора мнемониками ассемблера и только потом расшифровкой ))
И даже если использовать древнейшие трансляторы ассемблера, даже в этом случае любую недокументированную команду можно набить как DEFB байт, байт,...


Как Вы ещё получите доступ к машинному коду, если не через POKE и PEEK?

Также как это обычно делают программы для спектрума - загрузкой кодового блока и передачей ему управления. Загрузка в самом простом виде выполняется загрузкой файла кода из команд бейсика. В более извращённом продвинутом - кодовый блок загрузчика впихивается в тело бейсик программы. Ну и естественно структура загрузчика зависит от того с ленты или диска производится загрузка.


диапазон #0000-#FFFF можно было представить в десятичном виде, потому что я думаю не все читатели статьи пока понимают, что FFFF в десятичном представлении это 65535

Напротив если будете программировать в ассемблере под zx, забудьте как выглядят адреса и мнемоники в десятичном виде )) Практически все мониторы-отладчики и прочие используют шестнадцатеричное представление, поскольку оно намного удобнее для работы с маш-кодом.

Ну и немного в тему страниц памяти.
Запись в порт #7FFD (32765) имеет битовую структуру: %00BRSnnn,

где nnn - номер страницы (биты 0-2 (0-7): изначально как правило 0),
S - номер экрана (бит 3 (8): 0 - стандартный стр.5 , 1 - дополнительный стр.7),
R - номер ПЗУ ( бит 4 (16): 1 - BASIC 48 , 0 - BASIC 128 ),
B - блокировка 128 K ( бит 5 (32): 0 - доступно , 1 - заблокировано) - если заблокировать, то не разблокируется до перезагрузки.
старшие биты 6,7 ставить в 0 ( в пентагоне, кае и других клонах могут использоваться для дополнительной памяти)

В карте процессора страницы следуют:
#0000 - #3FFF ( 0 -16383) - ПЗУ
#4000 - #7FFF (16384 - 32767) - 5
#8000 - #BFFF (32768 - 49151) - 2
#C000 - #FFFF (49152 - 65535) - окно

Если воткнуть в окно скажем 5-ю или 2-ю страницу, то она будет доступна сразу по двум адресам и по своему стандартному расположению и по окну.

Запись в порт в Z80 на ассемблере производится командами:
out (c),a ( есть также out(c),reg , где reg = a,b,c,d,e,h,l )
out (n),a где n - короткий адрес порта. (не следует использовать для #7FFD)

В случае OUT (C),A и подобными на самом деле запись A ведётся в порт с адресом в регистровой паре BC
а в случае OUT (n),A старший байт адреса порта берется из самого A, то есть значение регистра A засылается в порт с адресом (A)*256+n

В былые времена наплодили много программ, демок и т.п. использующих короткую адресацию по #xxFD вместо #7FFD, в результате на многих компах (с расширением памяти выше 128 особенно) эти программы вылетали со скрипом ))

alex8418
27.01.2023, 21:49
Спасибо за объемлющие ответы по теме машинных кодов для машины 128 килобайт, пользователям: Dart Alver, Barmaley_m, и даже пользователю LW; хорошо было бы посмотреть живые примеры применения оператора OUT 32765! Получилось, что тема переродилась из программирования на 48 килобайт машине в программирование на 128 килобайт машине! Ну это не страшно, исправим!

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


Ну и немного в тему страниц памяти.
Запись в порт #7FFD (32765) имеет битовую структуру: %00BRSnnn,

out (c),a ( есть также out(c),reg , где reg = a,b,c,d,e,h,l )

Dart Alver в этих строках Вы ошибки не допустили? Непонятна формула %00BRSnnn и какие такие значения a,b,c,d,e,h,l присваиваемые reg?

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


Лучше учитесь читать в шестнадцатеричном виде числа, понятнее будет всё в дальнейшем.

Ассемблер это не программа, это представление команд процессора в виде, доступном(более понятном) для чтения человеком.
А то, что вы называете ассемблером, это всего навсего компилятор, да и то, актуальные версии компиляторов, как правило, понимают недокументированные команды процессора

Команда POKE понимает только десятичные числа и работает в встроенном BASIC спектрума, не требуя загрузки дополнительного ПО в машину! А почему тогда представление команд и компилятор имеет одно и тоже название? (НО КОМПИЛЯТОР - ЭТО ЖЕ ПРОГРАММА?)

Reobne
27.01.2023, 21:56
хорошо было бы посмотреть живые примеры применения оператора OUT 32765!
Для этого нужно в эмуляторе с отладчиком, поставить точку останова на запись в этот порт, и запускать всякие 128К программки.
А когда программка тормознётся - долго и вдумчиво изучать что там только что делал код.

Dart Alver
28.01.2023, 01:27
Dart Alver в этих строках Вы ошибки не допустили? Непонятна формула %00BRSnnn и какие такие значения a,b,c,d,e,h,l присваиваемые reg?

Хмм. Ну пожалуй про reg кривовато написал малость, не так надо было

out (c),a ( есть также out(c),reg , где reg = a,b,c,d,e,h,l )

а просто

out(c),reg , где reg = a,b,c,d,e,h,l

reg здесь это имя регистра (это не переменная а просто обозначение что параметром может быть один из регистров). Просто сократил чтобы не писать весь список : out (c),b , out (c),e и т.п.
также как ld reg1,reg2 - куча различных инструкций с разными регистрами в качестве аргументов.


А что непонятно в формуле %00BRSnnn ?
Знак % означает число в двоичном виде. Соответственно всё что в него входит - это соответствующие биты числа

Например этот код выставит по адресу #C000 страницу памяти с номером 7 :



ld bc,#7FFD
ld a,#17
out (c),a
; #17 = %00010111 -> 7-я страница (nnn=7), экран в 5-й странице (S=0),
; ПЗУ BASIC 48 (R=1), порт не блокируется (B=0)


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


хорошо было бы посмотреть живые примеры применения оператора OUT 32765!

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



10 CLEAR 45055
20 DATA 0,1,3,4,6,7
30 RESTORE 20
40 GO SUB 1000 : RANDOMIZE USR 15619 : REM : LOAD "scr0" CODE 49152
50 GO SUB 1000 : RANDOMIZE USR 15619 : REM : LOAD "scr1" CODE 49152
60 GO SUB 1000 : RANDOMIZE USR 15619 : REM : LOAD "scr3" CODE 49152
70 GO SUB 1000 : RANDOMIZE USR 15619 : REM : LOAD "scr4" CODE 49152
80 GO SUB 1000 : RANDOMIZE USR 15619 : REM : LOAD "scr6" CODE 49152
90 GO SUB 1000 : RANDOMIZE USR 15619 : REM : LOAD "scr7" CODE 49152
200 DATA 33,0,192,17,0,64,1,0,27,237,176,201
210 RESTORE 200
220 FOR i=45056 TO 45056+11
230 READ a : POKE i,a
240 NEXT i
300 RESTORE 20
310 FOR i=0 TO 5
320 GO SUB 1000
330 RANDOMIZE USR 45056
340 PAUSE 0 : NEXT i
350 GO TO 300
1000 READ a : OUT 32765,a+16 : RETURN


Для работы примера нужно каким либо граф-редактором предварительно создать на диске 6 файлов скриншотов с расширением C (CODE) длиной 6912 байт : "scr0","scr1","scr3","scr4",scr6","scr7

Програмка тупо грузит экраны по страницам памяти, создаёт совсем маленькую подпрограмку в кодах:


ld hl,#C000 ; 33,0,192
ld de,#4000 ; 17,0,64
ld bc,#1B00 ; 1,0,27
ldir ; 237,176
ret ; 201

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

goodboy
29.01.2023, 12:45
если вам так нужен беспонтовый пример чего можно делать из бейсика, то вот :
я бы ещё и `теневой` экран задействовал, так сказать для показа всего функционала.
а данные на страницы универсальней грузить в цикле, переменную можно добавить в имя файла.
load "scr"+str$ A code
...........
именно для basic128 out вообще не нужен, достаточно занести номер страницы в (23388) и он сам её выставит

LW
29.01.2023, 13:21
в basic128 щелкать страницами чревато сбросом

Dart Alver
29.01.2023, 15:29
я бы ещё и `теневой` экран задействовал, так сказать для показа всего функционала.
а данные на страницы универсальней грузить в цикле, переменную можно добавить в имя файла.
load "scr"+str$ A code

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


именно для basic128 out вообще не нужен, достаточно занести номер страницы в (23388) и он сам её выставит
Не работал с 128 бейсиком.
В былые времена на профи привык к сбросу в TR-DOS + 48-й бейсик с открытой доп. памятью. А 128 бейсик при наличии уже ZASMа, TASMа и STORMа не зашел. ))
---
Да на 128-м бейсике пример не работает. Предварительно нужно сбросить в 48-й. и TR-DOS инициализировать. Из 128-го это:
RANDOMIZE USR 0
RANDOMIZE USR 15616
RETURN
и затем набивать программу.

Либо, как сказал goodboy, заменить в 1000-й строке OUT 32765,a+16 на POKE 23388,a+16

alex8418
12.02.2023, 16:13
[QUOTE=Dart Alver;1171614]
Хоть я уже бейсик позабыл напрочь, но если вам так нужен беспонтовый пример чего можно делать из бейсика, то вот :



10 CLEAR 45055
20 DATA 0,1,3,4,6,7
30 RESTORE 20
40 GO SUB 1000 : RANDOMIZE USR 15619 : REM : LOAD "scr0" CODE 49152
50 GO SUB 1000 : RANDOMIZE USR 15619 : REM : LOAD "scr1" CODE 49152
60 GO SUB 1000 : RANDOMIZE USR 15619 : REM : LOAD "scr3" CODE 49152
70 GO SUB 1000 : RANDOMIZE USR 15619 : REM : LOAD "scr4" CODE 49152
80 GO SUB 1000 : RANDOMIZE USR 15619 : REM : LOAD "scr6" CODE 49152
90 GO SUB 1000 : RANDOMIZE USR 15619 : REM : LOAD "scr7" CODE 49152
200 DATA 33,0,192,17,0,64,1,0,27,237,176,201
210 RESTORE 200
220 FOR i=45056 TO 45056+11
230 READ a : POKE i,a
240 NEXT i
300 RESTORE 20
310 FOR i=0 TO 5
320 GO SUB 1000
330 RANDOMIZE USR 45056
340 PAUSE 0 : NEXT i
350 GO TO 300
1000 READ a : OUT 32765,a+16 : RETURN


Для работы примера нужно каким либо граф-редактором предварительно создать на диске 6 файлов скриншотов с расширением C (CODE) длиной 6912 байт : "scr0","scr1","scr3","scr4",scr6","scr7

Dart Alver спасибо за живой пример!!!