Assembler для начинающих


Текстовый режим



Текстовый режим


      Два текстовых режима цветного графического адаптера дают
    простой способ вывода символов на экран. В текстовых режимах
    цветная плата аналогична монохромному адаптеру, но она позволяет
    указать цвет каждого символа. Так же, как и в монохромной плате,
    каждая символьная позиция цветной платы имеет байт атрибутов. Этот
 
      Номер бита  7  6  5  4  3  2  1  0
              ЪДДВДДДДДДДДВДДВДДДДДДДДї
              і Мі Ф  О  Ні Яі СИМВОЛ і Фиг. 8.9 Байт атрибута
              АДДБДДБДДБДДБДДБДДБДДБДДЩ          для ЦГА
 



                                - 289 -    
 
 
 
    байт атрибутов определяет цвета символов и фона каждой позиции.
      На Фиг.8.9 показана структура байта атрибутов в цветном
    текстовом режиме. Три бита, помеченных Ф О Н, определяют один из
    восьми возможных цветов фона. Три бита СИМВОЛ определяют цвет
    символа. Бит Я также влияет на цвет символа: его установка делает
    цвет символа более ярким. Тем самым обеспечивается выбор одного из
    16 цветов символа. Байт атрибута управляет единственным символом,
    позволяя выбрать любую комбинацию цветов фона и символа каждой
    позиции. Старший бит, помеченный буквой М, обычно вызывает мигание
    символа. Установка бита мигания равным 1 заставляет контроллер
    дисплея переключать цвет символа между его цветом и цветом фона со
    скоростью примерно четыре раза в секунду. Так как символ,
    изображенный в цвете фона, невидим, то получается эффект мигания.
    Можно заменить бит мигания четвертым битом цвета фона, разрешив при
    этом 16 цветов фона и 16 цветов символа. Это делает один из битов
    регистра выбора цветов. Еще надо обратить внимание на то, что
    одинаковая установка цветов символа и фона означает, что вы не
    видите символ. Символ есть, но это все равно что пытаться увидеть
    северного медведя в пургу - все одного цвета. На Фиг. 8.10 показаны
    все 16 цветов, возможных в текстовом режиме.
 
      I    R        G    B      Цвет
      -------------------------------------
      0    0        0    0       черный
      0    0        0    1       синий
      0    0        1    0       зеленый
      0    0        1    1       морской волны
      0    1        0    0       красный
      0    1        0    1       магента
      0    1        1    0       коричневый
      0    1        1    1       светло-серый
      1    0        0    0       темно-серый
      1    0        0    1       голубой
      1    0        1    0       светло-зеленый
      1    0        1    1       светлый морской
      1    1        0    0       розовый
      1    1        0    1       светлый магента
      1    1        1    0       желтый
      1    1        1    1       белый
      ------------------------------------------- Фиг. 8.10 Цвета
                               (Фирма IBM, приоритет 1981 г.)
 
      Если вы сравните байт атрибута для ЦГА с атрибутами для
    монохромного адаптера на Фиг. 8.7, то увидите, что они аналогичны.
    Конечно, вы не можете указать цвета монхромному адаптеру, но все
    остальное совпадает. Поскольку цветная плата не поддерживает
    атрибут подчеркивания, то установка монохромного атрибута
    подчеркивания соответствует голубому символу на черном фоне.
 
      Такая организация байта атрибутов является попыткой сделать два
    видео адаптера по-возможности совпадающими. Каждый символ в буфере
    дисплея находится по четному адресу, а байт атрибутов - по
    нечетному. Память цветного дисплея находится на видео адаптере, но
    по другому адресу: у монохромного дисплея она имеет адрес 0B0000H,
   а у цветного - 0B8000H. О сходстве дисплеев говорит то, что если
    при модификации программы для монохромного дисплея на Фиг. 8.8,
    изменить содержимое указателя AT сегмента на значение 0B800H,
    программа будет верно работать и на цветной плате. То есть одна и
    та же программа работает на любом видео адаптере при минимуме
    изменений.
 
      Для управления адаптером на цветной плате также используется
    контроллер ЭЛТ 6845 фирмы Motorola. Два порта ввода-вывода этого
    контроллера имеют адреса ввода-вывода 3D4H и 3D5H. На самом деле
    контроллер 6845 имеет 18 внутренних регистров. Доступ ко всем
    регистрам осуществляется с помощью двух портов ввода-вывода и
    косвенной адресации. Для обращения к регистру микросхемы 6845,
    нужно сначала загрузить индекс регистра в порт 3D4H, а затем читать
    этот регистр или записать в него данные через порт 3D5H.
 
      Приведем пример, чтобы пояснить, как работает контроллер. На
    Фиг. 8.11 перечислены все 18 регистров микросхемы 6845. В примере
    мы используем только регистры R10 и R11. Эти регистры определяют
    начальную и конечную строки растра одного знакоместа для курсора.
    Каждый символ, порождаемый цветной платой, состоит из восьми строк
    растра, имеющих номера от 0 до 7. Вы можете поместить курсор в
    любых из этих восьми строк. Регистр R10 сообщает микросхеме 6845,
    на какой строке начинается курсор, а регистр R11 определяет
    последнюю строку курсора. ROM BIOS инициализирует курсор,
    находящийся на строках 6 и 7; это делается загрузкой числа 6 в R10
    и числа 7 в R11.
 
      Прогамма на Фиг.8.12(а) модифицирует курсор цветной графической
    платы. Она смещает курсор так, что он оказывается на верхних пяти
    строках растра вместо нижних двух. Сначала программа загружает в
    индексный регистр контроллера 6845 (3D4H) число 10, а затем
    записывает номер начальной строки, равный 0, в регистр данных
    (3D5H). Затем, поместив 11 в индексный регистр, она устанавливает
    номер конечной строки равным 4. Теперь курсор имеет вид мигающего
    блока в верхней части позиции символа, а не митающего
    подчеркивания. Подобный этому способ модификации курсора
    используется несколькими редактирующими программами (редакторами)
    персональной ЭВМ, включая встроенный редактор интерпретатор языка
    Бейсик. При установке режима вставки во время редактирования,
    курсор становится жирнее; интерпретатор Бейсика делает это, меняя
    параметры в микросхеме 6845.
 
      Вернувшись к Фиг. 8.11, можно увидеть, что в микросхеме 6845
    есть и другие регистры. Большинство из них управляет сигналами
    горизонтальной и вертикальной синхронизации телевизионного растра.
    Вы можете модифицировать коды в этих регистрах для каких-либо
    действий дисплеем. Например, команда MODE системы DOS, которая
    может сдвигать катринку на экране влево и вправо, модифицирует
    регистр R2, задающий положение строчного синхроимпульса.
      Если вы захотите поэкспериментировать с этими регистрами, вам
    придется писать короткие программы, делающие требуемые изменения.
            ЪДДДДДДДДВДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДВДДДДДДДДДДДВДДДДДДДДВДДДДДДДДї
            іРегистр і                    і Объект в  і          і            і
            і   # і    Регистр хранит          і программе і чтение і запись і
            ГДДДДДДДДЕДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДЕДДДДДДДДДДДЕДДДДДДДДЕДДДДДДДДґ
            і  R0 і  Гориз. сумма        і Символ    і     Нет  і      Да   і
            ГДДДДДДДДЕДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДЕДДДДДДДДДДДЕДДДДДДДДЕДДДДДДДДґ
            і  R1 і  Выводимая горизонталь     і Символ    і     Нет  і      Да   і
            ГДДДДДДДДЕДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДЕДДДДДДДДДДДЕДДДДДДДДЕДДДДДДДДґ
            і  R2 і  Гориз. поз. синхронизации і Символ    і     Нет  і      Да   і
            ГДДДДДДДДЕДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДЕДДДДДДДДДДДЕДДДДДДДДЕДДДДДДДДґ
            і  R3 і  Гориз. ширина синхронизации і Символ    і   Нет  і      Да   і
            ГДДДДДДДДЕДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДЕДДДДДДДДДДДЕДДДДДДДДЕДДДДДДДДґ
            і  R4 і  Вертикальный итог         і Симв. ряд і     Нет  і      Да   і
            ГДДДДДДДДЕДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДЕДДДДДДДДДДДЕДДДДДДДДЕДДДДДДДДґ
            і  R5 і  Общая вертикальн.коррекция      іСкан.строкиі     Нет  і      Да   і
            ГДДДДДДДДЕДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДЕДДДДДДДДДДДЕДДДДДДДДЕДДДДДДДДґ
            і  R6 і  Выводимая вертикаль       і Симв. ряд і     Нет  і      Да   і
            ГДДДДДДДДЕДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДЕДДДДДДДДДДДЕДДДДДДДДЕДДДДДДДДґ
            і  R7 і  Поз. вертикальной синхрон.      і Симв. ряд і     Нет  і      Да   і
            ГДДДДДДДДЕДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДЕДДДДДДДДДДДЕДДДДДДДДЕДДДДДДДДґ
            і  R8 і  Режим совмещения          і     -     і     Нет  і      Да   і
            ГДДДДДДДДЕДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДЕДДДДДДДДДДДЕДДДДДДДДЕДДДДДДДДґ
            і  R9 і  Макс.адрес скан. строки   іСкан.строкиі     Нет  і      Да   і
            ГДДДДДДДДЕДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДЕДДДДДДДДДДДЕДДДДДДДДЕДДДДДДДДґ
            і  R10      і  Начало курсора            іСкан.строкиі     Нет  і      Да   і
            ГДДДДДДДДЕДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДЕДДДДДДДДДДДЕДДДДДДДДЕДДДДДДДДґ
            і  R11      і  Конец курсора       іСкан.строкиі     Нет  і      Да   і
            ГДДДДДДДДЕДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДЕДДДДДДДДДДДЕДДДДДДДДЕДДДДДДДДґ
            і  R12      і  Начальный адрес (гориз.)  і     -     і     Нет  і      Да   і
            ГДДДДДДДДЕДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДЕДДДДДДДДДДДЕДДДДДДДДЕДДДДДДДДґ
            і  R13      і  Начальный адрес (строка)  і     -     і     Нет  і      Да   і
            ГДДДДДДДДЕДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДЕДДДДДДДДДДДЕДДДДДДДДЕДДДДДДДДґ
            і  R14      і  Курсор (Гориз.)           і     -     і     Да   і      Да    і
            ГДДДДДДДДЕДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДЕДДДДДДДДДДДЕДДДДДДДДЕДДДДДДДДґ
            і  R15      і  Курсор (Строка)           і     -     і     Да   і      Да    і
            ГДДДДДДДДЕДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДЕДДДДДДДДДДДЕДДДДДДДДЕДДДДДДДДґ
            і  R16      і  Световое перо (гориз.)    і     -     і     Да   і      Нет   і
            ГДДДДДДДДЕДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДЕДДДДДДДДДДДЕДДДДДДДДЕДДДДДДДДґ
            і  R17      і  Световое перо(строка)     і     -     і     Да   і      Нет   і
            АДДДДДДДДБДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДБДДДДДДДДДДДБДДДДДДДДБДДДДДДДДЩ

            Фиг. 8.11 Регистры микросхемы 6845
                 (с разрешения фирмы Motorola)
 
    Если попытаться изменять регистры с помощью утилиты DEBUG, то это
    может не сработать. Регистры R14 и R15 управляют позицией курсора,
    и если утилита DEBUG переместит курсор между вашими обращениями к
    индексному регистру и к регистру данных, изменения не произойдет.
    Так получилось потому, что утилита DEBUG изменила содержимое
    индексного регистра микросхемы 6845, и он уже больше не указывает
    на тот внутренний регистр, который вы хотели изменить.
 
      Другая интересная регистровая пара микросхемы 6845 - пара
    регистров начального адреса R12 и R13. Адаптер цветного
    графического дисплея имеет 16K байт памяти, а монохромная плата 4K
    байта. Дополнительная память в цветной плате используется для
    графических режимов, но она целиком в вашем распоряжении и в
    текстовых режимах. Для текстового режима 80*25 требуется 4K байта
    памяти, так что в буфере есть место для четырех разных страниц
    памяти. Сдвигать данные на экране можно переносом данных с одного
    места на другое, как это делалось на Фиг. 8.8. В случае же
    вертикального сдвига нужно лишь изменить начальный адрес в
    микросхеме 6845. Обычно начальный адрес равен 0. Если вы измените
    его на 80 (число символов в строке), отображение будет начинаться
    со второй строки. Это даст немедленный эффект сдвига всех данных
    экрана вверх на одну строку.
 
      На самом деле вы не изменяли данные, а сдвинули начало
    сканирования памяти дисплея. Можно рассматривать дисплей как окно
    80*25, через которое мы смотрим в 8192-символьный буфер дисплея.
 
      При использовании начального адреса для сдвига данных возникают
    сложности, когда вы приближаетесь к границе 16K байт. В этой точке
    отображение "заворачивается". Верхние строки извлекаются из конца
    буфера, а нижние строки - из его начала. Вы, конечно, сможете
    решить эту проблему, но для этого потребуются некоторые размышления
    и эксперименты.
 
    [Прим. перев.: стр. 252 текста оригинала в моей копии отсутствует.
    Очевидно, на ней находится только начало Фиг. 8.12]

           Microsoft (R) Macro Assembler Version 5.00              1/1/80 04:05:31
           Фиг. 8.12 Программа управления цветным дисплеем        Page   1-1
 
                                         PAGE    ,132
                                         TITLE   Фиг. 8.12 Программа управления цветным дисплеем
 
            0000                   STACK   SEGMENT STACK
            0000  0040[                  DW      64 DUP (?)
                  ????
                              ]
            0080                   STACK   ENDS
 
            0000                   DISPLAY_BUFFER  SEGMENT AT 0B800H
            0000                   DISPLAY_START   LABEL   WORD
            0000                   DISPLAY_BUFFER  ENDS
 
            = 03D4                       CRT_INDEX         EQU     03D4H
            = 03D5                       CRT_DATA          EQU     03D5H
            = 03DA                       CRT_STATUS      EQU     03DAH
            = 000A                       CURSOR_START    EQU     10          ; Регистры управления курсором
            = 000B                       CURSOR_END      EQU     11          ;      в контроллере дисплея 6845
 
            0000                   CODE    SEGMENT
                                         ASSUME  CS:CODE
            0000                   COLOR_GRAPHICS  PROC    FAR
            0000  1E                           PUSH    DS              ; Адрес возврата в ДОС
            0001  2B C0                  SUB     AX, AX
            0003  50                           PUSH    AX
 
                   Фиг. 8.12 Программа управления цветным дисплеем (начало)
                                   ;-----  Фиг. 8.12 (а) Изменение курсора
 
            0004  BA 03D4                      MOV     DX, CRT_INDEX
            0007  B0 0A                  MOV     AL, CURSOR_START      ; Установка индексного регистра
            0009  EE                           OUT     DX, AL                ;      6845 на регистр начала курсора
            000A  42                           INC     DX
            000B  B0 00                  MOV     AL, 0
            000D  EE                           OUT     DX, AL                ; Установка начала курсора
 
            000E  4A                           DEC     DX
            000F  B0 0B                  MOV     AL, CURSOR_END
            0011  EE                           OUT     DX, AL                ; Выбор регистра конца курсора
            0012  42                           INC     DX
            0013  B0 04                  MOV     AL, 4
            0015  EE                           OUT     DX, AL                ; Установка конца курсора
 
                                   ;-----  Фиг. 8.12 (б) Использование регистра состояния 6845
 
            0016  B8 0002                      MOV     AX, 2
            0019  CD 10                  INT     10H             ; Выбор символьного режима 80*25
            001B  B8 ---- R                    MOV     AX, DISPLAY_BUFFER
            001E  8E C0                  MOV     ES, AX                ; Адрес буфера дисплейной памяти
            0020  B8 0720                      MOV     AX, 0720H             ; Вывод начинается с пробела
            0023                   NEXT_CHAR:
            0023  BF 0000                      MOV     DI, 0
            0026  B9 0050                      MOV     CX, 80
            0029  F3/ AB                       REP     STOSW                 ; Вывод строки из 80 символов
            002B  FE C0                  INC     AL              ; Следующий символ
            002D  75 F4                  JNZ     NEXT_CHAR
 
            002F  BB 0720                      MOV     BX, 0720H
            0032                   NEXT_CHAR_1:
            0032  B9 0050                      MOV     CX, 80
            0035  BF 0000                      MOV     DI, 0
            0038  BA 03DA                      MOV     DX, CRT_STATUS        ; Порт состояния для адаптера
                                                                 ; цветного дисплея
            003B                   WAIT_NO_RETRACE:
            003B  EC                           IN      AL, DX                ; Проверка на обратный ход луча
            003C  A8 01                  TEST    AL, 1
            003E  75 FB                  JNZ     WAIT_NO_RETRACE       ; Запрещение прерываний
            0040  FA                           CLI
            0041                   WAIT_RETRACE:
            0041  EC                           IN      AL, DX
            0042  A8 01                  TEST    AL, 1
            0044  74 FB                  JZ      WAIT_RETRACE          ; Ожидание обратного хода луча
            0046  8B C3                  MOV     AX, BX                ; Выборка символа
            0048  AB                           STOSW                   ; Занесение в дисплейный буфер
            0049  FB                           STI                     ; Разрешение прерываний
            004A  E2 EF                  LOOP    WAIT_NO_RETRACE
            004C  FE C3                  INC     BL
            004E  75 E2                  JNZ     NEXT_CHAR_1
 
                                   ;-----  Фиг. 8.12 (в) Вывод линии по диагонали
 
                  Фиг. 8.12 Программа управления цветным дисплеем (продолжение)
            0050  B8 0004                      MOV     AX, 4
            0053  CD 10                  INT     10H             ; Установка графического
                                                                 ;      режима 320*200
            0055  06                           PUSH    ES
            0056  1F                           POP     DS
            0057  B3 32                  MOV     BL, 50                ; Число групп строк
            0059  B1 02                  MOV     CL, 2                 ; Счетчик сдвига
            005B  BF 0000                      MOV     DI, 0
            005E                   DOT_LOOP:
            005E  B0 C0                  MOV     AL, 0C0H              ; В AL маска первой точки в байте
            0060  88 05                  MOV     [DI], AL
            0062  81 C7 2000                   ADD     DI, 2000H             ; Переключение на нечетную строку
            0066  D2 E8                  SHR     AL, CL                ; Сдвиг до следующей точки в байте
            0068  88 05                  MOV     [DI], AL
            006A  81 EF 1FB0                   SUB     DI, 2000H-80          ; Переключение на четную строку
            006E  D2 E8                  SHR     AL, CL
            0070  88 05                  MOV     [DI], AL
            0072  81 C7 2000                   ADD     DI, 2000H             ; Переключение на нечетную строку
            0076  D2 E8                  SHR     AL, CL
            0078  88 05                  MOV     [DI], AL
            007A  81 EF 1FAF                   SUB     DI, 2000H-81          ; Переключение на четную строку,
            007E  FE CB                  DEC     BL              ;      следующий байт
            0080  75 DC                  JNZ     DOT_LOOP
 
                                   ;-----  Возврат к символьному режиму 80*25
 
            0082  B8 0002                      MOV     AX, 2
            0085  CD 10                  INT     10H
            0087  CB                           RET
            0088                   COLOR_GRAPHICS  ENDP
            0088                   CODE    ENDS
                                         END
 
           Фиг. 8.12 Программа управления цветным дисплеем (продолжение)
 
      Цветной графический адаптер имеет еще три регистра ввода-
    вывода. Регистр режима находится по адресу ввода-вывода 03D8H. Этот
    регистр устанавливает аппаратные переключатели различных режимов
    отображения. Например, вы можете установить бит 5 этого регистра в
    "0" и получить 16 цветов фона в текстовых режимах, а установка бита
    5 в "1" переключает 7-й бит атрибута на функцию мигания. Полное
    описание структуры этого регистра, и всех других, дано в
    техническом описании.
 
      Регистр выбора цвета находится по адресу ввода-вывода 03D8H.
    Этот регистр устанавливает цвет окаймления в текстовых режимах.
    Поскольку сам по себе текст не занимает весь экран, текст можно
    окружить каким-либо выбираемым цветом. Кроме того, регистр выбора
    цвета может управлять выбором палитр в графических режимов, как мы
    увидим в следующем разделе. Младшие 4 бита этого регистра
    устанавливают для окаймления один из 16 цветов, перечисленных на
    Фиг. 8.10.
 
      И наконец, регистр состояния по адресу ввода-вывода 3DAH
    организует информационную обратную связь между цветной платой и
    программой. Например, программа может использовать этот регистр для
    определения текущего состояния светового пера, если оно подключено
    к системе. Более важным является то, что регистр состояния
    сообщает, когда безопасно читать или записывать данные в дисплейный
    буфер.
 
      Не вдаваясь в технические детали, заметим, что чтение или
    запись данных в буфер дисплея цветной платы может вызвать "снег" на
    экране, если вы будете это делать в неподходящие моменты времени.
    Это случается только в текстовом режиме с высоким разрешением
    80*25. Вспомните, что ранее приводился пример на Фиг. 8.12, в
    котором постоянно записывались данные в буфер дисплея. Если для
    этого примера использовать цветную плату, на экране появится масса
    помех. Чтобы избежать этого, можно использовать регистр
    состояния.
 
      Существуют моменты, когда можно безопасно работать с данными в
    буфере дисплея. В такие моменты бит 0 регистра состояния равен 1.
    Нужно подождать, когда бит 0 станет равным 1, а затем читать или
    записывать данные. На Фиг. 8.12б изображена программа, которая
    записывает символ на экран дисплея. Первые строки этой программы
    записывают данные в буфер, не используя регистр состояния. Эта
    часть программы 224 раза записывает 80 симвлов в первую строку
    буфера, что эквивалентно заполнению экрана около девяти раз. Когда
    вы запустите программу, то увидите короткую вспышку помех в тот
    момент, когда будут записываться данные.
 
      Вторая часть программы на Фиг. 8.12б повторяет те же действия,
    но на этот раз проверяя бит состояния. Обратите внимание, что эта
    часть программы проверяет бит состояния двумя различными способами.
    Сначала она ждет, пока бит состояния не станет равным 0. Затем, как
    только он станет равен 1, программа записывает данные. Так сделано
    потому, что интервал, в течение которого можно записывать данные,
    очень мал, и если бы программа делала проверку только на равенство
    1, она могла бы захватить бит состояния непосредственно перед его
    обращением в 0. В этом случае, чтобы избежать помех, микропроцессор
    уже не может записывать данные достаточно быстро, но такая
    организация цикла гарантирует, что бит состояния захватывается в
    первый же момент, когда он становится равным 1.
 
      Используя бит состояния, вы уже не увидите на экране никаких
    помех, но и заметите, что выполнение программы стало гораздо
    медленнее. Выполняться медленнее программу заставляет
    дополнительное время, затрачиваемое на ожидание бита состояния.
    Если вам нужно записать на экране много данных - например,
    организовать горизонтальный сдвиг, как на Фиг. 8.8, то потребуется
    другой способ. Простейший способ - сбросить в нуль разряд
    отображения в регистре режима. Бит 3 регистра режима (3D8H)
    управляет отображением на дисплее. Если сбросить этот бит в 0,
    экран погаснет. Чтобы переслать много данных в буфер цветного
    дисплея, вы можете выключить отображение и переслать данные без
    проверки бита состояния. Поскольку отображение выключено, на экране
    не возникнут помехи. Когда пересылка блока закончится, включите
    отображение. Вы заметите короткое мигание изображения в момент его
    выключения и включения. Фирма IBM использует этот метод для
    обслуживания вертикального сдвига цветного дисплея.




Содержание раздела