                   Программирование под AmigaOS на асемблере

 Перед тем как начать изучение этой статьи, необходимо иметь элементарные понятия
о программировании на M68K асемблере и иметь понятие о том, как работает AmigaOS.

 Перед ее изучением рекомендуется прочитать следующую документацию:

 - Программирование под AmigaOS для начинающих, версия 2.1 beta (C) 1999 RDC
 - Amiga Machine Langs 
 - И любую документацию по ассемблеру процессоров Motorola 68k

 Все это доступно на русском языке.

 Эта статья будет написана по типу главы из книги AmigaMachineLang "Операционная
система".    В  ней  будут  обозреваться  те  моменты,  которые  не  освещены  в
AmigaMachineLang.   Компилятор, на который ориентированы примеры в данной статье
- DevPac.  Перед началом программирования обязательно сделайте сл.  строчку:

 include system.gs -этот файл должен идти в комплекте с DevPac

                             1. Открытие библиотек

 execbase = 4   ; базовый адрес exec.library всегда постоянен и находится по
                ;адресу 4

 move.l execbase,a6 ;адрес exec.library в A6
 move.l #dos,a1 ;имя библиотеки dos.library в A1
 move.l #39,d0  ;номер версии открываемой библиотеки, если версия окажется ниже
                ;указанной в D0, то библиотека не откроется
 jsr _LVOOpenLibrary(a6)
 move.l d0,dosbase  ;сохраняем возвращенный адрес библиотеки
 beq.s no_open  ;если 0, то библиотека не открылась

dosbase dc.l 0
dos dc.b 'dos.library',0

 Таким же образом открываются и др. библиотеки

                             2. Закрытие библиотек

 move.l execbase,a6 
 move.l dosbase(pc),a1
 jsr _LVOCloseLibrary(a6)
 beq.s no_open

 После открытия библиотеки ее необходимо ОБЯЗАТЕЛЬНО закрыть.

                              3. Работа с памятью

 Возможно несколько вариантов. Начнем со старого.

                                  * AllocMem *

 - Резервирование

 move.l execbase,a6
 move.l #byte,d0 ;кол-во байт для резервирования
 move.l #mode,d1 ;режим резервирования
 jsr _LVOAllocMem(a6) ;функция захвата памяти 
 move.l d0,address ; выделенной памяти
 beq error ;ошибка в случае невозможности зарезервировать указанный блок памяти

address dc.l 0

 - Режимы резервирования памяти

 $0 или MEMF_ANY - выделить память любого типа, при наличии FAST RAM выделяется
Fast, при наличии только CHIP RAM - Chip.
 $2 или MEMF_CHIP - выделить chip память
 $4 или MEMF_FAST - выделить fast память
 $10000 MEMF_CLEAR - очистить память после выделения

Примечание:

 Возможны комбинации.
 $10004 - захватить fast память и очистить после захвата
 $10002 - захватить chip память и очистить после захвата

 - "Освобождение"

 move.l #byte,d1 ;кол-во освобождаемых байт
 move.l address(pc),a1 ;адрес освобождаемого блока памяти
 move.l execbase,a6 
 jsr _LVOFreeMem(a6) ;освободить память
 beq error

 Примечание:
 Количество освобождаемых байт ВСЕГДА должно совпадать с количеством
резервируемых, иначе память не освободится.

                                  * AllocVec *

 Отличие  его  от  AllocMem  в  том,  что  при  освобождении памяти не требуется
заносить в d0 кол-во освобождаемых байт, об этом система помнит сама.

 - Резервирование

 move.l execbase,a6
 move.l #byte,d0 ;кол-во байт для резервирования
 move.l #mode,d1 ;режим резервирования (те же, что и для AllocMem)
 jsr _LVOAllocVec(a6) ;функция захвата памяти 
 move.l d0,address ; выделенной памяти
 beq error ;ошибка в случае невозможности зарезервировать указанный блок памяти

 - "Освобождение"

 move.l address(pc),a1 ;адресс освобождаемого блока памяти
 move.l execbase,a6 
 jsr _LVOFreeMem(a6) ;освободить память
 beq error

                                * Memory Pools *

 Этот  метод  появился  в  ОС  3.0.   Суть  этого  метода  в  том,  что  система
автоматически  при необходимости  резервирует блоки памяти одинакового заданного
объема,  а  требуемые  блоки  любого  размера  выделяются уже как бы внутри этих
блоков.   Когда  память внутри одного из блоков фиксированного объема кончается,
система  автоматически  захватывает  новый.   Соответственно,  если внутри блока
освобождается  последний  из  блоков  произвольного  размера,  он  автоматически
освобождается.

     Для создания Memory Pool используется функция Exec.library CreatePool:

 move.l execbase,a6
 move.l #mode,d0 ;режим резервирования (те же, что и для AllocMem)
 move.l #pool,d1 ;размер фиксированного блока памяти,
 move.l   #min_blok,d2   ;минимальный  объем  памяти,  при  превышении  которого
                         ;захватываемые  участки  памяти  будут размещаться не в
                         ;блоках   заданного   размера   вместе   с   остальными
                         ;участками,  а  в  своих собственных блоках (D2).  Этот
                         ;объем  должен  быть  МЕНЬШЕ  ИЛИ  РАВЕН  объему  блока
                         ;фиксированного размера.
 jsr _LVOCreatePool(a6)  ;создать Pool
 move.l  a0,newpool      ;CreatePool  возвращает указатель на заголовок  Pool'а,
                         ;или нуль в случае ошибки.
newpool dc.l 0

 Для   того,   чтобы  захватить  участок  памяти  произвольного  размера,  нужно
воспользоваться функцией AllocPooled (в той же библиотеке):

 move.l execbase,a6
 move.l newpool(pc),a0 ;указатель на начало Pool`а
 move.l #byte,d0 ;объем требуемой памяти
 jsr _LVOAllocPooled(a6)
 move.l d0,address ;указатель на начало блока памяти

            Освободить занимаемую память можно с помошью FreePooled:

 move.l execbase,a6
 move.l newpool(pc),a0 ;указатель на заголовок Pool'а
 move.l #byte,d0 ;длина в байтах
 move.l address(pc),a1 ;адрес освобождаемого участка
 jsr _FreePooled(a6)

   Функция DeletePool уничтожает Memory Pool:

 move.l execbase,a6
 move.l newpool(pc),a0 ;указатель на заголовок Pool`a
 jsr _DeletePool(a6)
