Прочитав новые посты узнал, что вы тут похоже разобрались как получать коды программ для машины без MSDOS. Т.о достаточно использовать EXE2BIN и сразу получается нужный код для загрузки в ОЗУ.
PVV в Вашем исходнике ПЗУ ошибка, потому что Вы использовали второй ORG, а объём кода увеличился на 1 байт. Потому те строки, что стоят после ORG 0FFF0H затёрли последний байт предыдущего кода. Потому, я ORG и не использую, а заполняю пустоту DB.
Также при каждой перетрансляции ПЗУ надо смотреть в листинге адреса LDBYTE, WRBYTE и MG_RET и подставлять эти адреса в секцию точек перехвата МГ-ввода (cas : tape-recorder) конфига эмулятора. Хотя пока это не особо надо, т.к МГ-ввод почему-то не работает.
Вообще очень неудобно, что в MASM и TASM арифметика не работает для адресов. Нельзя не только узнать сколько ячеек между двумя адресами, но и, например, при трансляции заголовка RKR или GAM файла я не могу вставить такую конструкцию:
Code: Select all
DB 0E6H
DB high RABADR, low RABADR
DB high ENDADR, low ENDADR
или такую:
Code: Select all
DB 0E6H
DB high RABADR, low RABADR
DB high (RABADR+RAZMER-1), low (RABADR+RAZMER-1)
Это может делать любой, самый убогий ассемблер для Z80/КР580, а крутой макро ассемблер для 8086 не может. Это получается, что мне надо всё делать вручную, смотреть в листинге трансляции адрес конца программы и вручную подставлять старший и младший байт в строки DB при каждой перетрансляции.
Подскажите кто-нибудь как использовать арифметику с адресами. Или хотя бы как выводить сообщения при трансляции. В 8-ми разрядных ассемблерах есть псевдо оператор '.PRINTX', который позволяет при трансляции выдать себе предупреждение, например, что происходит выход за допустимый размер кода или перехлёст фрагментов кода. А как сделать то же самое в ассемблере 8086 ? Видимо, придётся читать документацию на TASM и MASM.
Чтобы убедиться, что предыдущий код не залезает на адрес FFF0 и не будет затёрт из-за второго ORG, ставьте ключ USEORG на 0 и в листинге смотрите какой адрес получается у метки YFFF0. Если он отличается от FFF0, то надо изменить константу FREE, это число байтов FF, что заполняет пустоту до FFF0. И только потом можно вернуть ORG FFF0, да и то нежелательно, т.к тогда пустоты в ПЗУ заполняются нулями, а не FF-ами, что вызывает при прошивке ненужный износ УФ-РПЗУ.
Для проверки работы директивы G удобно использовать команду: G F815 или G на любую другую стандартную подпрограмму ПЗУ, что что-то выводит на экран. Вот правильный и оптимизированый код директивы G:
Code: Select all
DIR_G: MOV BX,offset WARMST
PUSH BX
JMP DS:[PAR_HL]
- - - Добавлено - - -
Почитал документацию про TASM 3.0 и узнал почему в строке ROR AX,4 при ключе .8086 не возникает ошибки, в то время как в TASM 2.0 ошибка возникает. Такая команда аппаратно есть только в 80186 и выше, а в 8086 есть только одинарные сдвиги. Оказывается сообщение об ошибке не выводится не потому, что ассемблер ошибочный, а потому, что с ключом .8086 ассемблер автоматически заменяет отсутствующую команду многократного сдвига на соответствующее число одинарных сдвигов.
PVV wrote:сделал в конфиге вставки:
Code: Select all
databin : Memory {
rom="Radio\O.bin"
}
mm : MemMap {
map[0][0000-0FFF]=databin
map[0][1000-7FFF]=mem1[01000]
...
Это изменение конфига никуда не годится. Оно просто погубило начало памяти, точнее эта память стала недоступна процессору, отчего перестали работать директивы T и M.
Что касается игры "Охота на уток", то попытка её трансляции выявила ещё кучу вопросов. Не понял как из программ делать вызовы ПЗУ F800. Команды CALL и JMP 8088-го процессора в отличие от КР580 не могут делать переход дальше чем на 32767, т.к вторым и третьим параметром команды у них не абсолютный адрес, как у КР580, а смещение от текущего адреса в диапазоне +/- 32767. Потому, хотя ПЗУ F800 и программа в начале ОЗУ находятся в общем сегменте кода, но внутрисегментный переход невозможен и команда CALL CS:F809 не работает.
Понятно, что нужно использовать FAR-вызов подпрограммы ПЗУ. Но не понял как в ассемблере задать такой вызов. До того не приходилось видеть исходников где бы ПЗУ вызывалось по CALL, только по INT. Похоже надо создать и объявить сегмент содержащий ПЗУ и объявить в нём FAR метку. Тогда CALL будет транслироваться в дальний вызов. Но как это сделать ?
Из предыдущих постов узнал, что из отладчика эмулятора EMU командой ^L можно в ОЗУ по любому адресу загрузить любой файл, так что для отладки это удобнее, чем компоновать ROM-диск. Но удивлён как "Охота на уток" могла у кого-то хоть частично работать. В таком виде её можно странслировать только в ОЗУ 8400...BFFF или в ПЗУ E000. Тогда оттуда программа будет "доставать" до ПЗУ F800 и внутрисегментные CALL F8xx будут работать, т.к расстояние меньше 32767.
Вот исходник игры. Как его переделать, чтобы правильно транслировалось?
Вот
более оптимизированный ROM-BIOS. Исправил DIR_G (были забыты скобки, так XLT86 конвертирует). Ужал ещё на два десятка байтов и встроил сообщение об ошибке, а то в базовом ПЗУ ошибка (символ '?') выводилась сразу в строке с промптом.