Инструменты пользователя

Инструменты сайта


msx:assembler_programming_guide-fakhrutdinov_bocharov:14

Это старая версия документа!


Первая страницаПредыдущая страницаНазад к обзору

Приложение 4. Пример организации связей с языком MSX-BASIC. "Универсальное меню"

Приведенная ниже программа на языке MSX-BASIC вызывает подпрограмму на языке ассемблера и передает ей адрес строкового массива, используя функцию VARPTR. Массив представляет собой меню. Строка массива, начинающаяся с символа пробел, считается комментарием. Пустая строка («») является признаком конца меню.

Подпрограмма на ассемблере рисует на экране (параметры SCREEN 0, WIDTH 80 — устанавливаются заранее) окно, размеры которого определяются программно, исходя из параметров переданного массива (Y — по количеству элементов массива, т.е. до пустой строки, X — по наиболее длинной строке). Координаты окна программа на языке MSX-BASIC передает функцией LOCATE X,Y, используя тот факт, что интерпретатор записывает значения X и Y в системные ячейки.

Строка-курсор устанавливается на первый возможный вариант выбора меню (комментарии пропускаются). Эту строку можно перемещать в пределах окна с помощью клавиш вверх/вниз. Выбор осуществляется нажатием клавиши ввод.

Выбранная строка отмечается галочкой, и программе на языке MSX-BASIC возвращается её номер. Если в момент выбора были нажаты клавиши <CTRL>+<Stop>, возвращается ноль. Обратите внимание: - Пользователь MSX-BASIC должен сам следить за размещением окна на экране. - В меню должен быть хотя бы один возможный выбор.

## 1. BASIC-программа ``` ┌─────────────── 0 rem © 1990 И.Бочаров 10 CLEAR 200,&HDC00 ' Резервируем память для подпр. 20 DIM A$(17) ' Определяем массив-меню 30 BLOAD«wnd.obj» ' Загружаем подпрограмму 40 VDP(13)=&HA4:COLOR = (4,0,0,4)' Устанавливаем цвета окна 50 VDP(14)=&HF0 60 DATA « Select:»,« ===============»,Brief,Full,Info,Tree, On/Off ^F1,« —————»,Name,Extension,Size,Time, UnsORted,« ————–»,Help infORmation,Exit to main menu,«» 70 FOR I=0 TO 16 ' Считываем меню 80 READ A$(I) 90 NEXT 100 DEFUSR=&HDC00 ' Адрес подпрограммы-меню 110 DEFUSR1=&HDC03 ' Подпрограмма очистки экрана 130 : 140 LOCATE 2,1 ' Устанавливаем координаты окна 150 GOSUB 230 ' Вызываем подпрограмму 160 LOCATE 20,6 170 GOSUB 230 180 LOCATE 26,0 190 GOSUB 230 200 GOTO 140 ' Зацикливаемся 210 : 230 A=USR1(0) ' Очищаем цвета на экране 240 A=USR(VARPTR(A$(0))) ' Вызываем подпрограмму 250 IF A THEN LOCATE 75,22:PRINT A;:RETURN ELSE CLS:PRINT USR1( «<Ctrl><Stop>»):END ' Обрабатываем результат 260 rem The end. └─────────────── ```

## 2. Подпрограмма на языке ассемблера ``` ┌─────────────── ; © 1990 by IgOR BOCHAROV. ; ;————— Константы и адреса ————————— ; cr EQU 13 ; Клавиша «Конец выбора» Up EQU 30 ; Клавиша вверх Down EQU 31 ; Клавиша вниз TheBeg EQU 0DC00h ; Отсюда наша программа трансл. GetHL EQU 2F8Ah ; Подпрограммы передачи значен. PutHL EQU 2F99h Base1 EQU 0F3B5h ; Здесь хран. адрес табл. цвет. CsrX EQU 0F3DDh ; Сюда LOCATE пишет X CsrY EQU 0F3DCh ; А сюда Y RdVram EQU 004Ah ; Чтение из VRAM WrVrHL EQU 004Dh ; Запись во VRAM SetWrt EQU 0053h ; Установка VDP для записи ChSns EQU 009Ch ; Опрос состояния буфера клав. ChGet EQU 009Fh ; Взятие символа из буфера BreakX EQU 00B7h ; Опрос <CTRL>+<Stop> ;————————————————————–

      ORG     TheBeg

;——————- Точки входа ——————————

      JP      Menu            ; Универсальное меню
      JP      ClMenu          ; Очищение таблицы цветов

;————– Вычисляем размер окна ————————- Menu: CALL GetHL ; [HL] - адрес первого элемента

      PUSH    HL              ; Адрес первого элемента
      LD      IY,Variab       ; Адрес блока переменных
      XOR     a               ; Инициируем переменный
      LD      (IY+dy),a       ; Число строк
      LD      (IY+dx),a       ; dx

l001: LD a,(HL) ; Длина очередной строки

      AND     a               ; Конец?
      JR      Z,l002          ; Если да, то выходим
      INC     (IY+dy)         ; Увеличиваем число строк
      INC     HL              ; + длина
      INC     HL              ; + адрес
      INC     HL
      CP      (IY+dx)         ; Больше dx?
      JR      C,l001          ; Если нет, то dx не меняем
      LD      (IY+dx),A
      JR      l001

;————— Вычисляем координаты окна ——————– l002: LD HL,(CsrY) ; x y

      DEC     H
      DEC     L
      LD      C,H             ; x
      LD      B,0
      LD      H,B
      ADD     HL,HL           ; * 2
      ADD     HL,HL           ; * 4
      ADD     HL,HL           ; * 8
      ADD     HL,HL           ; * 16
      LD      E,L
      LD      D,H
      ADD     HL,HL           ; * 32
      ADD     HL,HL           ; * 64
      ADD     HL,DE           ; * 80
      ADD HL,BC
      EX      DE,HL
      INC     (IY+dx)         ; dx
      INC     (IY+dx)         ; dx
      LD      b,(IY+dx)       ; dx
      LD      c,(IY+dy)       ; dy
      PUSH    DE              ; Для печати текста

;——————- Рисуем окно —————————— ; [DE] - x + y*80, [b] - dx, [c] - dy

      PUSH    BC
      PUSH    DE              ; Для подсветки

; Рисование окантовки окна

      LD      a,17h           ;  ─
      LD      HL,1819h        ; ┌ ┐
      CALL    WndL01

WndL02:

      LD      a,' '           ; ' '
      LD      HL,1616h        ; │ │
      CALL    WndL01
      DEC     c
      JR      NZ,WndL02
      LD      a,17h           ;  ─
      LD      HL,1A1Bh        ; └ ┘
      CALL    WndL01

;— Теперь подсвечиваем ————- NEXtColORInWindow:

      POP     HL              ; x,y
      POP     DE              ; dx,dy
      INC     D
      INC     D
      INC     D               ; dx = dx + 4
      INC     D
      INC     E               ; dy = dy + 2
      INC     E

WndLp1:

      PUSH    DE
      PUSH    HL
      CALL    FillColORTable  ; Заполняем строку
      POP     HL
      LD      DE,80           ; [y] = [y] + 1
      ADD     HL,DE
      POP     DE
      DEC     E               ; [dy] = [dy] - 1
      JR      NZ,WndLp1

;——————- Пишем текст в окне ———————–

      POP     HL
      LD      DE,80*1+3       ; Откуда начать писать
      ADD     HL,DE
      LD      D,H
      LD      E,L
      EX      (SP),HL         ; Адрес первой строки

l003: LD A,(HL) ; Длина очередной строки

      AND     A               ; Конец?
      JR      Z,l004          ; Если да, то выходим
      LD      B,A             ; Текущий dx
      PUSH    HL
      PUSH    DE
      DI
      LD      A,E             ; Младший байт адреса
      OUT     (99h),A
      LD      A,D             ; затем старший байт
      OR      40h             ; выставив 6 бит в 1
      OUT     (99h),A
      INC     HL
      LD      A,(HL)          ; Получаем адрес строки
      INC     HL
      LD      H,(HL)
      LD      L,A
      LD      C,98h           ; загрузить номер порта VDP
      OTIR                    ; вывести блок
      EI
      POP     HL
      LD      DE,80
      ADD     HL,DE
      EX      DE,HL           ; [DE] - следующий адрес
      POP     HL
      INC     HL
      INC     HL
      INC     HL
      JR      l003            ; Повторяем вывод

;——————- Выбор в меню —————————– l004: POP HL ; Адрес первой строки

      LD      C,0             ; Текущее состояние
      LD      D,C
      LD      E,D

l007: PUSH HL l008: ADD HL,DE

      CALL    RdVram
      CP      ' '             ; Пробел?
      JR      NZ,l006
      LD      DE,80
      JR      l008

l006: POP DE

      CP      17h             ; ─?
      JR      NZ,l009
      EX      DE,HL
      DEC     C

l009: INC C

      PUSH    BC              ; Состояние
      PUSH    HL              ; Стираем засветку
      LD      D,(IY+dx)
      DEC     HL
      CALL    ClearColORTable
      POP     HL
      POP     BC

;——————- InputKey:

      CALL    BreakX
      JR      NC,Input
      LD      C,0
      JR      Exit

Input: CALL ChSns ; Есть что-нибудь в буфере?

      JR      Z,Inputkey
      CALL    ChGet           ; Берем символ

;——————-

      CP      cr
      JR      NZ,CheckUp
      LD      A,'√'
      DEC     HL
      CALL    WrVrHL

Exit: LD H,0

      LD      L,C             ; Текущее состояние
      JP      PutHL

;——————- CheckUp:

      CP      Up
      JR      NZ,CheckDown
      LD      A,C
      DEC     A               ; А можно ли наверх?
      JR      Z,InputKey
      LD      C,A
      PUSH    BC
      PUSH    HL
      LD      D,(IY+dx)
      DEC     HL
      CALL    FillColORTable  ; Стираем курсор
      POP     HL
      LD      DE,-80          ; Смещение на строку вверх

l010: ADD HL,DE ; Новая позиция курсора

      CALL    RdVram
      CP      ' '
      JR      Z,l010          ; Сканируем пробелы
      LD      D,(IY+dx)
      PUSH    HL
      DEC     HL
      CALL    ClearColORTable
      POP     HL
      POP     BC
      JR      InputKey

;——————- CheckDown:CP Down

      JR      NZ,InputKey
      PUSH    HL
      LD      D,(IY+dx)
      PUSH    BC
      DEC     HL
      CALL    FillColORTable  ; Стираем курсор
      POP     BC
      POP     HL
      LD      DE,80
      JR      l007

;————————————————————– WndL01:

      PUSH    BC
      PUSH    DE
      PUSH    AF
      PUSH    BC
      LD      A,' '
      CALL    WrVram
      LD      A,H
      CALL    WrVram
      POP     BC
      POP     AF
      CALL    FillVm
      LD      A,L
      CALL    WrVram
      LD      A,' '
      CALL    WrVram
      POP     HL
      LD      BC,80
      ADD     HL,BC
      EX      DE,HL
      POP     BC
      RET

;————————————————————– ; Рисует цветную линию по координатам и размеру ; [HL] - y *80+ x; [d] - dx ; MoDIfy: AF, BC, DE, HL FillColORTable:

      LD      E,10000000b
      CALL    GetMaskColOR    ; Получить адрес и маску

WndLp4: CALL RdVram ; считать текущий байт WndLp3: OR E

      DEC     D               ; [dx] = [dx] - 1
      JP      z,WrVrHL
      RRC     E               ; Следующая маска
      JR      NC,WndLp3       ; Если не вышли из байта, то не
                              ; пишем
      CALL    WrVrHL          ; Иначе записываем
      INC     HL              ; Следующий адрес VRAM
      JR      WndLp4

;————————————————————– ; Очищает цветную линию ; [HL] - y *80+ x; [d] - dx ; MoDIfy: AF, BC, DE, HL ClearColORTable:

      LD      E,01111111b
      CALL    GetMaskColOR    ; Получить адрес VRAM и маску

WndLp5: CALL RdVram ; считать текущий байт WndLp6: AND E

      DEC     D               ; [dx] = [dx] - 1
      JP      Z,WrVrHL
      RRC     E               ; Следующая маска
      JR      C,WndLp6        ; Если не вышли из байта, то не
                              ; пишем
      CALL    WrVrHL          ; Иначе записываем
      INC     HL              ; Следующий адрес VRAM
      JR      WndLp5

;————————————————————– ; По координатам выдает адрес VRAM и маску ; [HL] - y*80 + x; ; [HL] - адрес Vram; [e] - маска GetMaskColOR:

      LD      A,L             ; Получаем из коор. физ. адрес
      LD      B,3
      SRL     H               ; [HL] = [HL] / 8
      RR      L
      DJNZ    $-4
      LD      BC,(Base1)
      ADD     HL,BC           ; Физический адрес VRAM
      CPl                     ; [a] = not([a])
      AND     00000111b       ; Бит, который надо установить
      LD      B,A
      INC     B
      RLC     E
      DJNZ    $-2
      RET

;————————————————————– ; Очистка цветной таблицы

ClMenu: LD DE,(Base1)

      LD      B,24*10
      XOR     A

;————————————————————– ; заполнение VRAM const [a], len [b], adr [DE] FillVm: DI

      PUSH    AF
      LD      A,E
      OUT     (99h),A
      LD      A,D
      OR      40h
      OUT     (99h),A
      POP     AF
      EX      (SP),HL
      EX      (SP),HL
      OUT     (98h),A
      INC     DE
      djNZ    $-3             ; повторить, если надо
      RET

;————————————————————– WrVram: EX DE,HL

      CALL    WrVrHL
      EX      DE,HL
      INC     DE
      RET

;————————————————————– Variab EQU $ dy EQU 1 dx EQU 2

      END

└─────────────── ```


Первая страницаПредыдущая страницаНазад к обзору

msx/assembler_programming_guide-fakhrutdinov_bocharov/14.1589200932.txt.gz · Последние изменения: 2020-05-11 15:42 — GreyWolf