Advertisement
Guest User

Untitled

a guest
Aug 4th, 2018
193
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 14.30 KB | None | 0 0
  1. Banking in IAR and ZX Spectrum 128K
  2.  by DimkaM
  3.  
  4.  ---00---
  5.  
  6. По просьбе телезрителей, а также для себя в качестве шпаргалки,
  7. решил описать работу с банкингом вIAR'е.
  8. Сразу хочу огорчить - банкинг не распространяется на переменные
  9. и константы (с некоторыми оговорками), только на исполняемый
  10. код.
  11. Данная статья предполагает, что вы уже ознакомились с моей
  12. статьёй вInfo Guide #11и у вас есть приложение кIG #11,так
  13. как я буду ссылаться на предыдущие примеры.
  14.  
  15. Сначала хочу дополнить предыдущую статью, так как многие не
  16. читают документацию и задают вопросы:
  17.  
  18. Q:Почему всё обёрнуто в модули?
  19. R:Как минимум, чтобы не было мешанины из меток, и при линковке
  20. (библиотек) линкуются только используемые модули.
  21.  
  22. Q:Как передавать/принимать параметры С-функций в ассемблере?
  23. R:До двух параметров передаётся в регистрах, остальные через
  24. стек.
  25. Если количество параметров неопределённо (printf(...) и т.п.),
  26. то все параметры передаются через стек.
  27. Первый параметр передаётся в E, DE, CDE или BCDE, в зависимости
  28. от разрядности значения.
  29. Если первый и второй параметры не шире 16 бит каждый, то второй
  30. параметр передаётся в регистрах B или BC, иначе через стек.
  31. Возвращаемое значение из функции передаётся в регистрах A (L при
  32. банкинге), HL, CHL или BCHL, в зависимости от разрядности
  33. значения.
  34.  
  35.  ---01---
  36.  
  37. Для начала нам необходимы процедуры для вызова (и возврата)
  38. процедур из переключаемых страниц.
  39. Вернее, они уже есть в библиотекеz80\inc\clz80b.r01,но они
  40. расчитаны на порт с восьмибитным адресом, да ещё и с чтением из
  41. него текущей страницы.
  42. Поэтому заменим (чтобы постоянно не линковать) в этой библиотеки
  43. нужные нам процедуры.
  44. Создадим директорию проектаfix_clz80b.
  45. Создадим в этой директории файлzx128k.s01со следующим
  46. содержимым:
  47.  
  48. ;так как нет аппаратной возможности узнать текущую страницу в
  49. ;окне 0xc000-0xffff,
  50. ;то каждая страница (участвующая в банкинге) будет хранить свой
  51. ;номер по адресу 0xFFFF.
  52.  MODULE MY_CURRENT_PAGE
  53.  PUBLIC MY_CURRENT_PAGE
  54. MY_CURRENT_PAGE=0xffff
  55.  ENDMOD
  56.  
  57. MODULE ?BANK_CALL_DIRECT_L08
  58.  PUBLIC ?BANK_CALL_DIRECT_L08
  59.  EXTERN MY_CURRENT_PAGE
  60.  RSEG RCODE
  61. ?BANK_CALL_DIRECT_L08:
  62.  push hl
  63.  ld hl,(MY_CURRENT_PAGE-1)
  64.  push bc
  65.  ld bc,0x7ffd
  66.  out (c),a
  67.  pop bc
  68.  ex (sp),hl
  69.  jp (hl)
  70.  ENDMOD
  71.  
  72.  MODULE ?BANK_LEAVE_32_L08
  73.  PUBLIC ?BANK_LEAVE_32_L08
  74.  EXTERN MY_CURRENT_PAGE
  75.  RSEG RCODE
  76. ?BANK_LEAVE_32_L08:
  77.  ld sp,ix
  78.  pop ix
  79.  pop de
  80.  inc sp
  81.  inc sp
  82.  pop af
  83.  push bc
  84.  ld bc,0x7ffd
  85.  out (c),a
  86.  pop bc
  87.  ret
  88.  ENDMOD
  89.  
  90.  MODULE ?BANK_LEAVE_DIRECT_L08
  91.  PUBLIC ?BANK_LEAVE_DIRECT_L08
  92.  PUBLIC ?BANK_FAST_LEAVE_L08
  93.  EXTERN MY_CURRENT_PAGE
  94.  RSEG RCODE
  95. ?BANK_LEAVE_DIRECT_L08:
  96.  ld sp,ix
  97.  pop ix
  98.  pop de
  99.  pop bc
  100. ?BANK_FAST_LEAVE_L08:
  101.  pop af
  102.  push bc
  103.  ld bc,0x7ffd
  104.  out (c),a
  105.  pop bc
  106.  ret
  107.  ENDMOD
  108.  
  109.  MODULE ?BANK_CALL_DIRECT_EXAF_L08
  110.  PUBLIC ?BANK_CALL_DIRECT_EXAF_L08
  111.  EXTERN MY_CURRENT_PAGE
  112.  RSEG RCODE
  113. ?BANK_CALL_DIRECT_EXAF_L08:
  114.  ex af,af'
  115.  ld a,(MY_CURRENT_PAGE)
  116.  push af
  117.  ex af,af'
  118.  push bc
  119.  ld bc,0x7ffd
  120.  out (c),a
  121.  pop bc
  122.  jp (hl)
  123.  END
  124.  
  125. Далее нам понадобится файлzx128k.batс содержимым:
  126. ..\z80\bin\az80 -uu -b -v0 zx128k.s01
  127. copy ..\z80\lib\clz80b.r01 ..\z80\lib\clzx128k.r01 /Y
  128. ..\z80\bin\xlib -c "fetch-modules zx128k.r01
  129. ..\z80\lib\clzx128k.r01 MY_CURRENT_PAGE MY_CURRENT_PAGE"
  130. ..\z80\bin\xlib -c "replace-modules zx128k.r01
  131. ..\z80\lib\clzx128k.r01"
  132.  
  133. Запускаем его, и у нас появляется библиотека
  134. ..\z80\inc\clzx128k.r01- это копия библиотекиclz80b.r01с
  135. заменёнными процедурами банкинга.
  136. Проектfix_clz80bнам больше не понадобится.
  137.  
  138.  ---02---
  139.  
  140. Сейчас мы переделаем под банкинг процедуры печати из предыдущей
  141. статьи.
  142. Создадим директориюmylibb,в ней поддиректориюlist.
  143. Скопируем в текущий проект файлыmylib.c(переименовав в
  144. putchar.c) иgraf.s01из директорииmylib(см. статью вInfo
  145. Guide #11).
  146.  
  147. graf.s01отредактируем следующим образом:
  148. БыстрыйПиксель и таблицу положим в небанкируемую память, т.е. в
  149. сегмент RCODE. Соответственно, выход из неё - обычный ret.
  150.  MODULE fast_set_pix
  151.  PUBLIC fast_set_pix,fast_set_pix_table
  152.  RSEG RCODE ;НЕбанкируемый сегмент
  153. fast_set_pix ;http://zxdn.narod.ru/coding/zg1etud2.txt
  154. ...
  155. тело процедуры
  156. ...
  157.  ret ;обычный выход
  158.  RSEG ALIGN8
  159. fast_set_pix_table
  160.  DEFS 1024
  161.  ENDMOD
  162.  
  163. Инициализацию таблиц и медленныйпиксель определим в банкируемый
  164. сегмент CODE, в этом случае необходимо использовать библиотечную
  165. процедуру для выхода.
  166.  MODULE fast_set_pix_init
  167.  PUBLIC fast_set_pix_init
  168.  EXTERN fast_set_pix_table,?BANK_FAST_LEAVE_L08
  169.  RSEG CODE ;банкируемый сегмент
  170. fast_set_pix_init
  171. ...
  172. тело процедуры
  173. ...
  174.  ;ret заменим на выход из страницы:
  175.  JP LWRD ?BANK_FAST_LEAVE_L08
  176.  ENDMOD
  177.  
  178.  MODULE little_set_pix
  179.  PUBLIC little_set_pix
  180.  EXTERN ?BANK_FAST_LEAVE_L08
  181.  RSEG CODE ;банкируемый сегмент
  182. little_set_pix
  183. ...
  184. тело процедуры
  185. ...
  186.  ;ret заменим на выход из страницы:
  187.  JP LWRD ?BANK_FAST_LEAVE_L08
  188.  END
  189.  
  190. Создадимbuild.bat:
  191. ..\z80\bin\iccz80 -v0 -mb -uua -b -q -x -K -gA -z9 -t4 -T
  192. -Olist\ -Llist\ -Alist\ -I"../z80/inc/" putchar.c
  193. ..\z80\bin\az80 -uu -b -v0 -Olist\ graf.s01
  194.  
  195. Опция -mb указывает на необходимость компиляции всех функций под
  196. банкинговые вызовы, т.к. библиотечные puts и printf ожидают
  197. банкируемую функцию putchar.
  198.  
  199. Туда же добавим компоновку библиотеки:
  200. del /Q mylibb.r01
  201. ..\z80\bin\xlib -c "fetch-mod list\putchar.r01 mylibb.r01"
  202.  "fetch-mod list\graf.r01 mylibb.r01"
  203. "LIST-ALL-SYMBOLS mylibb.r01 list\mods.txt"
  204.  
  205. Собираем библиотеку этим батником.
  206.  
  207. В новом файле'mylibb.h'опишем переменную MY_CURRENT_PAGE, она
  208. пригодится, если понадобится узнать текущую страницу:
  209. extern unsigned char MY_CURRENT_PAGE;
  210.  
  211. И остальные функции, не забывая указывать модификаторы банкинга:
  212. banked void scr_init(char atribute);
  213. #ifdef FASTPIXEL
  214. banked void fast_set_pix_init(void);
  215. non_banked void fast_set_pix(unsigned char x,unsigned char y);
  216. #define set_pix fast_set_pix
  217. #define set_pix_init fast_set_pix_init
  218. #else
  219. #define set_pix_init()
  220. banked void little_set_pix(unsigned char x,unsigned char y);
  221. #define set_pix little_set_pix
  222. #endif
  223.  
  224. Модификатор banked можно не указывать, т.к. по умолчанию у нас
  225. всё банкируется, но лучше указать - потом может пригодиться.
  226.  
  227.  ---03---
  228.  
  229. Итак, наконец-то, подготовка к HelloWorld прошла. Проверим, что
  230. у нас получилось.
  231. Создадим проект'HelloWorld',в нем поддиректорииlistиbin
  232.  
  233. ФайлLnk.xcl:
  234. -cZ80 //процессор
  235. //-P(CODE)CODE=[C000-FFFF]*2+10000,
  236.  //[3C000-3FFFF]*2+10000,[6C000-6FFFF]*2+10000 //выделяем банки
  237.  //0,1,3,4,6,7 под банкинг (5 и 2 не юзаем, т.к. прибиты)
  238. //но мы ещё учтём бит (в порту 7ffd) выбора ПЗУ 48К. Если нужно
  239. //ПЗУ 128К, то используйте предыдущую строчку:
  240. -P(CODE)CODE=[10C000-10FFFE]*2+10000,
  241.  [13C000-13FFFE]*2+10000,[16C000-16FFFE]*2+10000
  242. -Z(CODE)RCODE,CDATA0,CONST,CSTR,CCSTR=6000-7FFF//сегменты
  243.  //памяти с константами и кодом
  244. -Z(DATA)DATA0,IDATA0,UDATA0,ECSTR,ALIGN8|8,CSTACK+200=8000-BFFF
  245.  //сегменты стека, переменных и т.п.
  246. -e_medium_write=_formatted_write//конфигурация printf/sprintf
  247. -e_medium_read=_formatted_read//конфигурация scanf/sscanf
  248. ../mylibb/mylibb//линкуем свою библиотеку
  249. -C ../z80/lib/clzx128k//подключаем библиотеку ИАРа
  250. -FMOTOROLA
  251. -o list/aout.a01
  252. -l list/cout.html
  253. -xehinms//включим всё для полноты картины
  254. -R
  255. -w47//подавляем предупреждения, от которых я пока не понял,
  256.  //как избавиться
  257.  
  258. Файл build.bat:
  259. ..\z80\bin\iccz80 -v0 -mb -uua -q -e -K -gA -s9 -t4 -T -Llist\
  260.  -Olist\ -Alist\ -I"../z80/inc/" main.c
  261. ..\z80\bin\az80 -Olist\ -Dbanking Cstartup.s01
  262. ..\z80\bin\xlink -Ilist main cstartup -f Lnk.xcl
  263.  
  264. Скопируемcstartupиз предыдущей статьи, добавим нумерацию
  265. страниц, добавив следующий код сразу после меткиinit_C:
  266. #ifdef banking
  267. #if NOT proc64180
  268.  EXTERN MY_CURRENT_PAGE
  269.  ld hl,MY_CURRENT_PAGE
  270.  ld bc,0x7ffd
  271.  ld a,0x17
  272. bankIniLoop:
  273.  REPT 2
  274.  out (c),a
  275.  ld (hl),a
  276.  dec a
  277.  ENDR
  278.  dec a
  279.  cp 0x0e
  280.  jr nz,bankIniLoop
  281. #endif
  282. #endif
  283.  
  284. Создадимmain.c:
  285.  
  286. #include <stdio.h>
  287. #include <intrz80.h>
  288. #include <math.h>
  289. //#define FASTPIXEL
  290. #include "../mylibb/mylibb.h"
  291. void KbdScan(void){
  292.  printf("Keyboard scan: 0x%02X\r",input(0x00fe));
  293. }
  294. C_task void main(void){
  295.  unsigned char x=0;
  296.  scr_init(0x07<<3);
  297.  set_pix_init();
  298.  puts("Hello World!");
  299.  do{
  300.  set_pix(x,(sin((double)x/20)*20+95));
  301.  }while(++x);
  302.  while(1) KbdScan();
  303. }
  304.  
  305. Компилируем батником.
  306.  
  307.  ---04---
  308.  
  309. Опять засада: что делать с файломlist\aout.a01!?
  310. Этот файл в форматеmotorola s-records.
  311. Для преобразования файлаaout.a01воспользуемся сторонней
  312. утилитойSRecord- её вы сможете найти в приложении к этой
  313. газете.
  314.  
  315. Добавим вbuild.bat(внимание! рассчитано на стартовый адрес
  316. 0x6000!):
  317.  
  318. @echo off
  319. ..\z80\srecord\srec_cat list\aout.a01 -offset -0x6000 -crop 0
  320. 0x6000 -o bin\code.c -Binary
  321. FOR %%i IN (00,01,03,04,06,07,10,11,13,14,16,17) do
  322.  ..\z80\srecord\srec_cat list\aout.a01 -offset -0x%%~iC000
  323.  -crop 0 0x4000 -o bin\%%~i.c -Binary
  324. for /R bin\ %%i in (*.c) do (if %%~zi==0 (del /Q %%i)
  325.  ELSE (echo crop file:%%~nxi size:%%~zi out^(7FFD^),0x%%~ni))
  326. echo on
  327.  
  328. В директорииbinсоздастся бинарный файлcode,который
  329. необходимо загрузить и запустить с адреса0x6000,а также файлы
  330. с номером (с учётом бита выбора ПЗУ) страницы в имени - их,
  331. естественно, надо загрузить по страницам.
  332.  
  333. Возможно, у вас есть свои методы создания загрузчика и образа
  334. диска. Если нет, то можете добавить следующую строчку в
  335. build.bat:
  336. ..\z80\bin\build128k.bat buildscl
  337.  
  338. И получите на выходе scl-файл со всеми файлами и загрузчиком.
  339. Запускаем и наслаждаемся чистым синусом.
  340.  
  341.  * * *
  342.  
  343. В следующей серии мы рассмотрим грязные хаки. К примеру, как
  344. положить локальные переменные и константы в банкируемый сегмент.
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement