Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- Banking in IAR and ZX Spectrum 128K
- by DimkaM
- ---00---
- По просьбе телезрителей, а также для себя в качестве шпаргалки,
- решил описать работу с банкингом вIAR'е.
- Сразу хочу огорчить - банкинг не распространяется на переменные
- и константы (с некоторыми оговорками), только на исполняемый
- код.
- Данная статья предполагает, что вы уже ознакомились с моей
- статьёй вInfo Guide #11и у вас есть приложение кIG #11,так
- как я буду ссылаться на предыдущие примеры.
- Сначала хочу дополнить предыдущую статью, так как многие не
- читают документацию и задают вопросы:
- Q:Почему всё обёрнуто в модули?
- R:Как минимум, чтобы не было мешанины из меток, и при линковке
- (библиотек) линкуются только используемые модули.
- Q:Как передавать/принимать параметры С-функций в ассемблере?
- R:До двух параметров передаётся в регистрах, остальные через
- стек.
- Если количество параметров неопределённо (printf(...) и т.п.),
- то все параметры передаются через стек.
- Первый параметр передаётся в E, DE, CDE или BCDE, в зависимости
- от разрядности значения.
- Если первый и второй параметры не шире 16 бит каждый, то второй
- параметр передаётся в регистрах B или BC, иначе через стек.
- Возвращаемое значение из функции передаётся в регистрах A (L при
- банкинге), HL, CHL или BCHL, в зависимости от разрядности
- значения.
- ---01---
- Для начала нам необходимы процедуры для вызова (и возврата)
- процедур из переключаемых страниц.
- Вернее, они уже есть в библиотекеz80\inc\clz80b.r01,но они
- расчитаны на порт с восьмибитным адресом, да ещё и с чтением из
- него текущей страницы.
- Поэтому заменим (чтобы постоянно не линковать) в этой библиотеки
- нужные нам процедуры.
- Создадим директорию проектаfix_clz80b.
- Создадим в этой директории файлzx128k.s01со следующим
- содержимым:
- ;так как нет аппаратной возможности узнать текущую страницу в
- ;окне 0xc000-0xffff,
- ;то каждая страница (участвующая в банкинге) будет хранить свой
- ;номер по адресу 0xFFFF.
- MODULE MY_CURRENT_PAGE
- PUBLIC MY_CURRENT_PAGE
- MY_CURRENT_PAGE=0xffff
- ENDMOD
- MODULE ?BANK_CALL_DIRECT_L08
- PUBLIC ?BANK_CALL_DIRECT_L08
- EXTERN MY_CURRENT_PAGE
- RSEG RCODE
- ?BANK_CALL_DIRECT_L08:
- push hl
- ld hl,(MY_CURRENT_PAGE-1)
- push bc
- ld bc,0x7ffd
- out (c),a
- pop bc
- ex (sp),hl
- jp (hl)
- ENDMOD
- MODULE ?BANK_LEAVE_32_L08
- PUBLIC ?BANK_LEAVE_32_L08
- EXTERN MY_CURRENT_PAGE
- RSEG RCODE
- ?BANK_LEAVE_32_L08:
- ld sp,ix
- pop ix
- pop de
- inc sp
- inc sp
- pop af
- push bc
- ld bc,0x7ffd
- out (c),a
- pop bc
- ret
- ENDMOD
- MODULE ?BANK_LEAVE_DIRECT_L08
- PUBLIC ?BANK_LEAVE_DIRECT_L08
- PUBLIC ?BANK_FAST_LEAVE_L08
- EXTERN MY_CURRENT_PAGE
- RSEG RCODE
- ?BANK_LEAVE_DIRECT_L08:
- ld sp,ix
- pop ix
- pop de
- pop bc
- ?BANK_FAST_LEAVE_L08:
- pop af
- push bc
- ld bc,0x7ffd
- out (c),a
- pop bc
- ret
- ENDMOD
- MODULE ?BANK_CALL_DIRECT_EXAF_L08
- PUBLIC ?BANK_CALL_DIRECT_EXAF_L08
- EXTERN MY_CURRENT_PAGE
- RSEG RCODE
- ?BANK_CALL_DIRECT_EXAF_L08:
- ex af,af'
- ld a,(MY_CURRENT_PAGE)
- push af
- ex af,af'
- push bc
- ld bc,0x7ffd
- out (c),a
- pop bc
- jp (hl)
- END
- Далее нам понадобится файлzx128k.batс содержимым:
- ..\z80\bin\az80 -uu -b -v0 zx128k.s01
- copy ..\z80\lib\clz80b.r01 ..\z80\lib\clzx128k.r01 /Y
- ..\z80\bin\xlib -c "fetch-modules zx128k.r01
- ..\z80\lib\clzx128k.r01 MY_CURRENT_PAGE MY_CURRENT_PAGE"
- ..\z80\bin\xlib -c "replace-modules zx128k.r01
- ..\z80\lib\clzx128k.r01"
- Запускаем его, и у нас появляется библиотека
- ..\z80\inc\clzx128k.r01- это копия библиотекиclz80b.r01с
- заменёнными процедурами банкинга.
- Проектfix_clz80bнам больше не понадобится.
- ---02---
- Сейчас мы переделаем под банкинг процедуры печати из предыдущей
- статьи.
- Создадим директориюmylibb,в ней поддиректориюlist.
- Скопируем в текущий проект файлыmylib.c(переименовав в
- putchar.c) иgraf.s01из директорииmylib(см. статью вInfo
- Guide #11).
- graf.s01отредактируем следующим образом:
- БыстрыйПиксель и таблицу положим в небанкируемую память, т.е. в
- сегмент RCODE. Соответственно, выход из неё - обычный ret.
- MODULE fast_set_pix
- PUBLIC fast_set_pix,fast_set_pix_table
- RSEG RCODE ;НЕбанкируемый сегмент
- fast_set_pix ;http://zxdn.narod.ru/coding/zg1etud2.txt
- ...
- тело процедуры
- ...
- ret ;обычный выход
- RSEG ALIGN8
- fast_set_pix_table
- DEFS 1024
- ENDMOD
- Инициализацию таблиц и медленныйпиксель определим в банкируемый
- сегмент CODE, в этом случае необходимо использовать библиотечную
- процедуру для выхода.
- MODULE fast_set_pix_init
- PUBLIC fast_set_pix_init
- EXTERN fast_set_pix_table,?BANK_FAST_LEAVE_L08
- RSEG CODE ;банкируемый сегмент
- fast_set_pix_init
- ...
- тело процедуры
- ...
- ;ret заменим на выход из страницы:
- JP LWRD ?BANK_FAST_LEAVE_L08
- ENDMOD
- MODULE little_set_pix
- PUBLIC little_set_pix
- EXTERN ?BANK_FAST_LEAVE_L08
- RSEG CODE ;банкируемый сегмент
- little_set_pix
- ...
- тело процедуры
- ...
- ;ret заменим на выход из страницы:
- JP LWRD ?BANK_FAST_LEAVE_L08
- END
- Создадимbuild.bat:
- ..\z80\bin\iccz80 -v0 -mb -uua -b -q -x -K -gA -z9 -t4 -T
- -Olist\ -Llist\ -Alist\ -I"../z80/inc/" putchar.c
- ..\z80\bin\az80 -uu -b -v0 -Olist\ graf.s01
- Опция -mb указывает на необходимость компиляции всех функций под
- банкинговые вызовы, т.к. библиотечные puts и printf ожидают
- банкируемую функцию putchar.
- Туда же добавим компоновку библиотеки:
- del /Q mylibb.r01
- ..\z80\bin\xlib -c "fetch-mod list\putchar.r01 mylibb.r01"
- "fetch-mod list\graf.r01 mylibb.r01"
- "LIST-ALL-SYMBOLS mylibb.r01 list\mods.txt"
- Собираем библиотеку этим батником.
- В новом файле'mylibb.h'опишем переменную MY_CURRENT_PAGE, она
- пригодится, если понадобится узнать текущую страницу:
- extern unsigned char MY_CURRENT_PAGE;
- И остальные функции, не забывая указывать модификаторы банкинга:
- banked void scr_init(char atribute);
- #ifdef FASTPIXEL
- banked void fast_set_pix_init(void);
- non_banked void fast_set_pix(unsigned char x,unsigned char y);
- #define set_pix fast_set_pix
- #define set_pix_init fast_set_pix_init
- #else
- #define set_pix_init()
- banked void little_set_pix(unsigned char x,unsigned char y);
- #define set_pix little_set_pix
- #endif
- Модификатор banked можно не указывать, т.к. по умолчанию у нас
- всё банкируется, но лучше указать - потом может пригодиться.
- ---03---
- Итак, наконец-то, подготовка к HelloWorld прошла. Проверим, что
- у нас получилось.
- Создадим проект'HelloWorld',в нем поддиректорииlistиbin
- ФайлLnk.xcl:
- -cZ80 //процессор
- //-P(CODE)CODE=[C000-FFFF]*2+10000,
- //[3C000-3FFFF]*2+10000,[6C000-6FFFF]*2+10000 //выделяем банки
- //0,1,3,4,6,7 под банкинг (5 и 2 не юзаем, т.к. прибиты)
- //но мы ещё учтём бит (в порту 7ffd) выбора ПЗУ 48К. Если нужно
- //ПЗУ 128К, то используйте предыдущую строчку:
- -P(CODE)CODE=[10C000-10FFFE]*2+10000,
- [13C000-13FFFE]*2+10000,[16C000-16FFFE]*2+10000
- -Z(CODE)RCODE,CDATA0,CONST,CSTR,CCSTR=6000-7FFF//сегменты
- //памяти с константами и кодом
- -Z(DATA)DATA0,IDATA0,UDATA0,ECSTR,ALIGN8|8,CSTACK+200=8000-BFFF
- //сегменты стека, переменных и т.п.
- -e_medium_write=_formatted_write//конфигурация printf/sprintf
- -e_medium_read=_formatted_read//конфигурация scanf/sscanf
- ../mylibb/mylibb//линкуем свою библиотеку
- -C ../z80/lib/clzx128k//подключаем библиотеку ИАРа
- -FMOTOROLA
- -o list/aout.a01
- -l list/cout.html
- -xehinms//включим всё для полноты картины
- -R
- -w47//подавляем предупреждения, от которых я пока не понял,
- //как избавиться
- Файл build.bat:
- ..\z80\bin\iccz80 -v0 -mb -uua -q -e -K -gA -s9 -t4 -T -Llist\
- -Olist\ -Alist\ -I"../z80/inc/" main.c
- ..\z80\bin\az80 -Olist\ -Dbanking Cstartup.s01
- ..\z80\bin\xlink -Ilist main cstartup -f Lnk.xcl
- Скопируемcstartupиз предыдущей статьи, добавим нумерацию
- страниц, добавив следующий код сразу после меткиinit_C:
- #ifdef banking
- #if NOT proc64180
- EXTERN MY_CURRENT_PAGE
- ld hl,MY_CURRENT_PAGE
- ld bc,0x7ffd
- ld a,0x17
- bankIniLoop:
- REPT 2
- out (c),a
- ld (hl),a
- dec a
- ENDR
- dec a
- cp 0x0e
- jr nz,bankIniLoop
- #endif
- #endif
- Создадимmain.c:
- #include <stdio.h>
- #include <intrz80.h>
- #include <math.h>
- //#define FASTPIXEL
- #include "../mylibb/mylibb.h"
- void KbdScan(void){
- printf("Keyboard scan: 0x%02X\r",input(0x00fe));
- }
- C_task void main(void){
- unsigned char x=0;
- scr_init(0x07<<3);
- set_pix_init();
- puts("Hello World!");
- do{
- set_pix(x,(sin((double)x/20)*20+95));
- }while(++x);
- while(1) KbdScan();
- }
- Компилируем батником.
- ---04---
- Опять засада: что делать с файломlist\aout.a01!?
- Этот файл в форматеmotorola s-records.
- Для преобразования файлаaout.a01воспользуемся сторонней
- утилитойSRecord- её вы сможете найти в приложении к этой
- газете.
- Добавим вbuild.bat(внимание! рассчитано на стартовый адрес
- 0x6000!):
- @echo off
- ..\z80\srecord\srec_cat list\aout.a01 -offset -0x6000 -crop 0
- 0x6000 -o bin\code.c -Binary
- FOR %%i IN (00,01,03,04,06,07,10,11,13,14,16,17) do
- ..\z80\srecord\srec_cat list\aout.a01 -offset -0x%%~iC000
- -crop 0 0x4000 -o bin\%%~i.c -Binary
- for /R bin\ %%i in (*.c) do (if %%~zi==0 (del /Q %%i)
- ELSE (echo crop file:%%~nxi size:%%~zi out^(7FFD^),0x%%~ni))
- echo on
- В директорииbinсоздастся бинарный файлcode,который
- необходимо загрузить и запустить с адреса0x6000,а также файлы
- с номером (с учётом бита выбора ПЗУ) страницы в имени - их,
- естественно, надо загрузить по страницам.
- Возможно, у вас есть свои методы создания загрузчика и образа
- диска. Если нет, то можете добавить следующую строчку в
- build.bat:
- ..\z80\bin\build128k.bat buildscl
- И получите на выходе scl-файл со всеми файлами и загрузчиком.
- Запускаем и наслаждаемся чистым синусом.
- * * *
- В следующей серии мы рассмотрим грязные хаки. К примеру, как
- положить локальные переменные и константы в банкируемый сегмент.
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement