Этюды.

© Alone Coder

         1.Обмен содержимого двух
             областей памяти.

   Процедурка меняет местами два куска па-
мяти,расположенные по круглым адресам. Па-
раметры: HL=addr1, D='addr2, B='size.

EXCH  LD E,L
      LD C,(HL)
      LD A,(DE)
      LD (HL),A
      LD A,C
      LD (DE),A
      INC L
      JR NZ,EXCH
      INC H
      INC D
      DJNZ EXCH
      RET


     2.Копирование между страничками.

   Очень удобная процедурка для сохранения
STS (или Real Commander) в другой странич-
ке, если ваша программа портит page 7.
   Параметры: HL=addr, D=page from, E=page
to. Копируется всё вплоть до адреса #ffff.

COPPG LD BC,32765
COPpg OUT (C),D
      LD A,(HL)
      OUT (C),E
      LD (HL),A
      INC L
      JR NZ,COPpg
      INC H
      JR NZ,COPpg
      RET

   Если  скорость не важна, можно заменить
окончание цикла на
      ...
      INC HL
      INC H
      DEC H
      JR NZ,COPpg
      RET

   Чтобы  ограничить  копируемый фрагмент,
можно использовать цикл по LX:
      ...
      INC L
      JR NZ,COPpg
      INC H
      DEC LX
      JR NZ,COPpg
      RET

   Можно короче,но медленнее:
      ...
      INC HL
      LD A,H
      CP ...
      JR NZ,COPpg
      RET


      3.Чтение с диска в виртуальное
          адресное пространство.

   Во  многих  системных  программах может
использоваться виртуальное адресное прост-
ранство, обычно  занимающее  4 странички и
адресующееся  через  подпрограммы чтения и
записи байта,параметром которых служит ви-
ртуальный адрес от 0 до #ffff.
   Допустим,у нас есть процедурка нахожде-
ния номера следующей странички этого адре-
сного  пространства по номеру предшествую-
щей. Пускай она называется "NXTPAG". Пусть
также  номер первой используемой странички
равен 16. Попробуем написать загрузку фай-
ла длиной  до  #ff секторов от начала этой
области (или по крайней  мере с "круглого"
адреса в ней):

   [Программа NXTPAG.H]

        LD A,16
        EX AF,AF'
;A'=FIRST PAGE (порядок страниц 0,3,6,1!)
        LD HL,#C000
;HL=ADDRESS (должен делиться на 256)
        LD DE,#100
;DE=TRACK & SECTOR
        LD B,100
;B=sectors
        LD C,5
LDNXPAG PUSH BC
        EX AF,AF'
        PUSH AF
        CALL OUTME
        LD A,B
        ADD A,H
        LD A,B
        JR NC,$+5
        XOR A
        SUB H
        LD B,A
        LD (LDNXPGA+1),A
        CALL #3D13 ;TR-DOS
        LD HL,#C000
        POP AF

        CALL NXTPAG ;NEXT PAGE CALCULATED

        POP BC
        LD DE,(23796) ;NEXT TRACK & SECTOR
        EX AF,AF'
        LD A,B
LDNXPGA SUB 64
        LD B,A
        JR NZ,LDNXPAG
        RET

;ЖЕЛАТЕЛЬНО ВСЕ ОБРАЩЕНИЯ К ВЕРХНЕЙ ПАМЯТИ
;ПРОИЗВОДИТЬ ЧЕРЕЗ ЭТУ ПРОЦЕДУРКУ:
OUTME   PUSH BC
        LD BC,32765
;      LD (PG),A  ;(если IM 2)
        OUT (C),A
        POP BC
        RET

;CALCULATE NEXT PAGE:
NXTPAG  ADD A,3
        AND 23
        RET

   В данном случае процедура записи той же
области памяти на диск полностью эквивале-
нтна, меняется только регистр C.
   Если нужно грузить не с начала памяти,а
с другого  адреса (обязательно круглого!),
то достаточно вставить в начало вышеприве-
дённой процедурки  вычисление  странички и
адреса  в ОЗУ, соответствующего  заданному
виртуальному.


      4.Чтение-запись в виртуальное
          адресное пространство
          с точностью до байта.

   Сложности начинаются тогда,когда требу-
ется грузить блок по виртуальному адресу с
точностью до байта. Для этого придётся ос-
вободить  область  памяти #bf00-#bfff (это
потребуется для загрузки дробных секторов:
всех,пересекающих страничку,и последнего).
Алгоритмы  Load и Save теперь сильно отли-
чаются. Более того,они такие сложные,что я
до сих пор не уверен, что  в программе нет
глюков ;(.
   Смотри сорс LOADSAVE.H... Он вытащен из
пока не дописанного "Программатора" by Tot
& я, и там  (внимание!)  другая  нумерация
страничек.