Goto... Search.. Hext Change.. Follou Previous 10 глава




Для того, чтобы приведенная программа работала, следует загрузить драйвер мыши, который инициализирует последовательный интерфейс и саму мышь. В состав этого драйвера входит свой обработчик прерываний. Мы замещаем его адрес в векторе ОСИ адресом нашего обработчика, и поскольку в программе не предусмотрено сцепление обработчиков, на время действия программы стандартная обработка прерываний от мыши отключается. Перед завершением программы содержимое вектора ОСИ восстанавливается, и мышь опять начинает работать, как обычно.

Каждое нажатие (или отпускание) клавиши мыши, так же, как и ее перемещение, в действительности вырабатывают не по одному, а по три последовательных прерывания с рахтичными кодами в порте данных ин­терфейса. Так, нажатие левой клавиши мыши дает последовательность кодов 60h, 0, 0, нажатие правой клавиши — последовательность 50h, О, О, отпускание любой клавиши — 40h, 0, 0, перемещение вверх — 4Ch, О, 3Fh, перемещение вниз — 40h, О, 1 и т.д. Таким образом, по-настоящему надо было сохранять в обработчике прерываний все три кода и затем ана­лизировать всю последовательность. Мы для простоты ограничились ана­лизом только первого кода. Как видно из приведенного выше перечня, анализ одного кода не дает возможность отличить, например, отпускание клавиши от перемещения вниз.

Коды, генерируемые мышью, могут зависеть от ее типа, что надо учи-|*Тывать при подготовке этого примера. Для получения значений генериру-[емых кодов можно предусмотреть в-обработчике прерываний вывод их на ркран с помощью функции прерывания 10h BIOS, как это было сделано, [например, в примере 3-5, или прямым выводом в видеобуфер. Следует столько иметь в виду, что перехват любого прерывания от последователь-



Глава 3


ного интерфейса должен обязательно сопровождаться чтением из его порта данных, так как интерфейс может принять очередной байт данных только после чтения предыдущего и освобождения своего регистра данных.

;Пример 3-12, Программирование мыши в режиме прерываний
.586;Будут команды новых процессоров

code segment use!6;16-разрядное приложение?

assume CS:code,DS:code;Данные в сегменте команд

main proc -g

push CS;Настроим DS i4:

pop DS;на сегмент команд::

;Сохраним обработчик прерываний последовательного порта ^

mov AX,350Ch;Функция 35h, вектор OCh - u

int 21h:,;
mov word ptr old_Oc,BX;Сохраним смещение

mov word ptr old_Oc+2,ES;Сохраним сегмент w
;Установим наш обработчик прерываний последовательного порта!

mov AX,250Ch;Функция 25h, вектор OCh /t-

mov DX,ofiset new_0c;Адрес нашего обработчика г--.

int 21h

;Остановим программу функцией ввода с клавиатуры \
mov AH,01h
int 21h
восстановим исходный обработчик драйвера мыши

  mov AX,250Ch
  Ids DX,old Oc
  int 21h
  mov AX,4COOh
  int 21h
main endp  
new_ ,0c proc
  pusha  
  push DS
  push ES
  mov DX,3F8h
  in AL,DX
  cmp AL,60h

;Функция 25h, вектор OCh?;«

;Сохраненный адрес •:J,

;3авершим профамму ';i

;Сохраним все регистры;Сегментные регистры не сохраняются командой pusha;Порт данных; Прочитаем

;Левая клавиша — код 60h
je ibtn;Переход на отработку

cmp AL,50h;Правая клавиша — код 50h

je rbtn; Переход на отработку

;3авершение обработчика прерываний
outret: pop ES;Восстановим сегментные

pop DS;регистры

imov AL,20h;Команда EOI

out 20h,AL ';в контроллер прерываний

рора; Восстановим все регистры

iret;Выход и^ прерывания


манды и алгоритмы



 


;Если нажата левая клавиша мыши

Ibtn: mov AH,lEh;Атрибут символов желтый по

;синему

mov SI,offset msgdn;Aflpec выводимой строки
jmp commn;Ha общую часть вывода

;Если нажата правая клавиша мыши

rbtn: mov AH,2Eh;Атрибут символов желтый по

; зеленому mov SI,offset msgup;Mpec вьтодимой строки

;Общая часть вывода на экран диагностической строки

commn: mov
mov ES,BX
push cs
pop DS
mov CX,6
mov DI.2000
eld  
scr: lodsb  
stosw  
loop scr
jmp outret

BX,OB800h;Настроим ES;на видеобуфер; Настроим DS;на наш сегмент;Число выводимых символов;Смегцение на экране;Движение вперед;АЬ=очередной символ;Из АХ на экран;Цикл

;После вывода завершить;обработку прерывания

endp dd
new__0c old Oc

О;Ячейка для исходного

; вектора

msgdn db msgup db code ends stk segment stack dw 128 dup(O) stk ends end main

"Левая!";Выводимые сообщения

"Правая"


Приведенный пример с точки зрения его структуры построен обыч­ным образом. Исходное содержимое вектора ОСЬ сохраняется в ячейке old_0c и используется перед завершением программы для восстановления вектора. Для упрощения установки обработчика прерываний программа написана без сегмента данных; ее немногие данные размещены в сегмен­те команд. Поскольку в начале программы регистр DS настраивается на сегмент команд, адресация к данным (в основной программе) возможна через DS, Для того, чтобы можно было наблюдать обработку прерываний от мыши, основная программа после выполнения инициализирующих действий останавливается с помощью функции Olh DOS ожидания ввода символа с клавиатуры. После нажатия любой клавиши программа завер­шается, восстановив предварительно исходное состояние вектора после­довательного порта.



Глава 3


Действия, которые должны инициироваться нажатием левой или пра­вой.клавиш мыши (например, включение или выключение некоторого оборудования), в программе заменены выводом на экран коротких диаг­ностических сообщений. Вывод осуществляется прямой записью в видео­буфер, поскольку, как уже говорилось ранее, в обработчике аппаратных прерываний нельзя использовать функции DOS и рискованно — функ­ции BIOS. Вывод на экран с помощью команд обработки строк lodsb и stosw требует настройки большого количества регистров — в DS:SI дол­жен находиться адрес строки-источника, в ES:DI адрес позиции в видео­буфере, в СХ число выводимых символов. Кроме этого, в обработчике прерываний используются регистры АХ, ВХ и DX. Для сохранения всех регистров общего назначения используется команда pusha, а для их вос­становления команда рора. Однако эти команды не принимают в расчет сегментные регистры, и их приходится сохранять и восстанавливать от­дельными командами.

С восстановлением регистров может возникнуть некоторая сложность. Обработчик прерывания должен завершаться посылкой в контроллер пре­рываний команды EOI, а для этого необходим регистр AL. Поэтому восста­новление регистров, во всяком случае, регистра АХ, необходимо выпол­нять после команды EOI. С другой стороны, команда EOI разблокирует нижележащие уровни прерываний в контроллере прерываний (см. гл. 3), что может привести к прохождению через контроллер очередного (вло­женного в наше) прерывания, которое прервет наш обработчик в точке, где еще не восстаношгсны регистры. Это неминуемо приведет к краху си­стемы. Однако в процессоре предусмотрены меры устранения этого не­приятного явления. Остановимся на них более подробно.

Процессор, приняв любой сигнал прерывания, сбрасывает флаг IF в своем регистре флагов, запрещая тем самым все аппаратные прерывания. Поэтому вход в обработчик прерываний всегда осуществляется при зап­рещенных прерываниях. Блокировка нижележащих уровней в контролле­ре прерываний просто накладывается на этот общий запрет и новых огра­ничений не вносит.

Если в тексте обработчике прерываний нет команды разрешения пре­рываний sti, то прерывания будут запрещены до самого его конца, до завершающей команды iret. Эта команда извлекает из стека и восстанав­ливает исходное содержимое регистров CS:IP, а также регистра флагов. В момент прерывания в регистре флагов был безусловно установлен флаг IF, иначе прерывание не могло бы возникнуть. Восстановление регистра флагов приводит к установке этого флага и разрешению всех аппаратных прерываний, но уже после завершения обработчика прерываний. Таким образом, снятие аппаратной блокировки прерываний командой EOI в действительности не приводит к разрешению прерываний, и любые стро­ки, стоящие после этой команды, выполняются при запрещенных пре­рываниях. В результате никаких проблем с восстановлением регистров после команды EOI не возникает.


Команды и алгоритмы



 


Обычно, однако, используется другой вариант построения обработ­чика прерываний. В этом варианте в начале программы обработчика вы­полняется команда sti, устанавливающая флаг IF и разрешающая все ап­паратные прерывания, кроме тех, которые заблокированы в контроллере прерываний. В результате программа обработчика может быть прервана любым прерыванием более высокого уровня IRQ (т.е. уровня с меньшим номером), но не прерывается сигналами прерываний этого же и более низких уровней. Такое построение обработчиков прерываний удобно тем, что «более важные» прерывания, например, от таймера или клавиатуры, могут быть обработаны без задержки. Для того, чтобы исключить возмож­ные неприятности с восстановлением регистра АХ после команды EOI, перед ней прерывания запрещаются командой cli и структура обработчи-;ка прерываний приобретает приблизительно такой вид:

sti

pusha;Сохранение регистров

;Тело обработчика

cli Запрещение всех прерываний

mov AL,20h;Команда EOI

out 20h,AL;контроллсру прерываний

рора;Восстановление регистров

irct;Возврат из обработчика

Команды рора и irct выполняются в этому случае при запрещенных [Прерываниях, но после отработки команды iret в регистре флагов восста->;навливастся его исходное содержимое (в котором IF = 1), и прерывания, I таким образом, снова разрешаются.


Глава 4. РАСШИРЕННЫЕ ВОЗМОЖНОСТИ

,, СОВРЕМЕННЫХ МИКРОПРОЦЕССОРОВ

4.1. Архитектурные особенности

Операционная система MS-DOS, язык ассемблера МП 86 и методы программирования микропроцессоров корпорации Intel разрабатывались применительно к 16-разрядному процессору 8086 и тому режиму, кото­рый впоследствии получил название реального. Появление процессора 80386 знаменовало собой начало нового этапа в развитии операционных систем и прикладного программирования — этапа многозадачных графи­ческих операционных систем защищенного режима типа Windows и 32-разрядных прикладных программ. При этом, как уже отмечалось во введе­нии, все архитектурные средства 86-го процессора входят в состав любого современного процессора, который, таким образом, можно условно раз­делить на две части — МП 86 и дополнительные средства, обеспечиваю­щие защищенный режим, 32-разрядную адресацию и прочее. Из этих до­полнительных средств можно выделить те, которые обеспечивают защи­щенный режим, и в реальном режиме не используются (во всяком случае, явным образом; в действительности, процессор, даже работая в реальном режиме, использует по крайней мере некоторые из этих средств). Сюда, например, относятся регистры таблиц дескрипторов, регистры тестиро­вания и отладки, привилегированные команды защищенного режима, система страничного отображения адресов и др. С другой стороны, часть новых свойств современных процессоров можно использовать и в реаль­ном режиме, выполняя программы под управлением MS-DOS. Сюда прежде всего относится использование 32-битовых операндов, некоторых новых команд процессора и расширенных возможностей старых команд. Настоя­щая глава будет в основном посвящена именно этим средствам процессо­ров 80386, i486 и Pentium, которые в дальнейшем мы будем обобщенно называть 32-разрядными процессорами. Вопрос о программировании за­щищенного режима слишком сложен, чтобы его можно было осветить в рамках этой книги, хотя основные принципы защищенного режима будут описаны.

32-разрядные процессоры содержат несколько десятков программно-адресуемых регистров (не считая регистров сопроцессора), из которых шесть являются 16-разрядными, а остальные — 32-разрядными. Регистры при­нято объединять в семь групп: регистры общего назначения (или регистры данных), регистры-указатели, сегментные регистры, упраатяющие реги­стры, регистры системных адресов, отладочные регистры и регистры тес­тирования. Кроме того, в отдельную группу выделяют счетчик команд и регистр флагов. Регистры, используемые в реальном режиме, показаны на рис. 4.1.


Расширенные возможности соврелмнных микропроцессоров



 


Решстры данных

Биты 31 16 15

 

 

 

 

 

 

 

ЕАХ ЕВХ ЕСХ EDX   АН АХ AL
 
  ВН ВХ BL
 
  СН СХ CL
 
  DH DX DL

Аккумулятор Базовый регистр Счетчик Регистр данных


Регистры-указатели

Биты 31 16 15


 

 

 

 

 

 

 

 

 

 

 

 

 

ESI EDI ЕВР ESP   SI Индекс источника Индекс приемника Указатель базы Указатель стека
   
  D,
   
  ВР
   
  SP

Сегментные регистры

Регистр сегмента команд Регистр сегмента данных Регистр дополнительного сегмента данных Регистр дополнительного сегмента данных Регистр дополнительного сегмента данных Регистр сегмента стека

Биты 15 О

Указатель командРегистр флагов
IP
EFLAFS

CS

Рис. 4.1. Основные регистры 32-разрядных процессоров.



Глава 4


Как видно из рис. 4.1, регистры общего назначения и регистры-указа­тели отличаются, от аналогичных регистров МП 86 тем, что они являются 32-разрядными. Соответственно, к их мнемоническим обозначениям до­бавлена буква Е (от extended, расширенный).

Для сохранения совместимости с ранними моделями процессоров допускается обращение к младшим половинам всех регистров, которые имеют те же мнемонические обозначения, что и в МП 86 (АХ, ВХ,.СХ, DX, SI, DI, ВР и SP). Естественно, сохранена возможность работы с младшими (AL, BL, CL и DL) и старшими (АН, ВН, СН и DH) поло­винками регистров МП 86. Однако старшие половины 32-разрядных реги­стров не имеют мнемонических обозначений и непосредственно недо­ступны. Для того, чтобы прочитать, например, содержимое старшей по­ловины регистра ЕАХ (биты 31... 16) придется сдвинуть все содержимое ЕАХ на 16 бит вправо (в регистр АХ) и прочитать затем содержимое АХ. Все регистры общего назначения и указатели программист может исполь­зовать по своему усмотрению для временного хранения адресов и данных размером от байта до двойного слова. Так, например, возможно исполь­зование следующих команд:


mov EAX,OFFFFFFFFh mov AX,OFFFFh mov AL,OFFh


;Работа с двойным словом (32 бит); Работа со словом (16 бит); Работа с байтом (8 бит)


Все сегментные регистры, как и в МП 86, являются 16-разрядными. В их состав включено еще два регистра — FS и GS, которые могут исполь­зоваться для хранения сегментных адресов двух дополнительных сегмен­тов данных. Таким образом, при использовании расширенных возможно­стей современных процессоров программе одновременно доступны четы­ре сегмента данных, а не два, как в МП 86.

Регистр указателя команд также является 32-разрядным и обычно при описании процессора его называют EIP. Младшие шестнадцать разрядов этого регистра соответствуют регистру IP процессора МП 86. Весь регистр EIP используется только в 32-разрядных приложениях; в 16-разрядных программах адреса могут быть только 16-разрядными и, соответственно, для адресации в программном сегменте используется младшая половина регистра Е1Р.

Регистр флагов принято называть EFLAGS (от extended flags, расши­ренные флаги). Хотя он имеет длину 32 бит, только младшие 18 бит (да и то не все) содержат значащую информацию. Дополнительно к шести флагам состояния (CF, PF, AF, ZF, SF и OF) и трем флагам управле­ния состоянием процессора (TF, IF и DF), назначение которых было описано в гл. 1, он включает новые флаги задачи, рестарта и виртуаль­ного режима, а также двухбайтовое поле привилегий ввода-вывода. Все эти биты используются только в защищенном режиме и здесь рассмат­риваться не будут.


Расширенные возможности современных микропроцессоров



4.2. Дополнительные режимы адресации

Режимы адресации 32-разрядных процессоров разработаны, исходя из требований образования 32-битового смещения. Другими словами, они предназначены для 32-разрядных приложений, в которых сегменты дан­ных или стека (как, впрочем, и сегменты команд) могут иметь размеры до 232 = 4 Гбайт. Однако в реальном режиме размер любого сегмента огра­ничивается величиной 216 = 64 Кбайт, и 32-битовые смещения не имеют смысла. С другой стороны, ничто не мешает нам использовать для образо­вания 16-битового смещения 32-разрядные регистры (ЕВХ, ESI и проч.), если, конечно, их реальное содержимое не будет превышать величины FFFFh. Указание в качестве операндов команд 32-разрядных регистров позволяет использовать дополнительные возможности 32-разрядных про­цессоров по части адресации памяти, что в некоторых случаях может ока­заться полезным. Следует подчеркнуть, что речь идет здесь только о тех операндах, или, правильнее сказать, аргументах команды, которые опи­сывают косвенную (через регистры) адресацию памяти.

В отличие от МП 86, где базовыми регистрами могут быть только ВХ и! ВР, а индексными только SI и DI, 32-разрядные процессоры допускают | использование в качестве и базовых, и индексных практически всех реги­стров общего назначения. Таким образом, вполне законна команда вида

mov EAX,[ECX][EDX]

Второе отличие заключается в возможности масштабирования содер­жимого индексного регистра, т.е. умножения его на заданный в команде коэффициент, который может принимать значения 1, 2, 4 или 8. Пример такой адресации:

inc word ptr [EAX][ECX*2]

Еще раз подчеркнем, что дополнительные режимы косвенной адрсса-I ции требуют использования 32-разрядных регистров. Команды

inc word ptr [AX][ECX*2]

или

inc word ptr [EAX][CX*2]

рассматриваются ассемблером, как неправильные.

Режимы косвенной адресации памяти, предоставляемые 32-разряд­ными процессорами при использовании 32-разрядных регистров, изобра­жены на рис. 4.2.

Из рисунка видно, что в качестве базового можно использовать все

регистры общего назначения, включая даже указатель стека ESP. При этом,

если в качестве базового выступает один из регистров ESP или ЕВР, то

по умолчанию адресация осуществляется через сегментный регистр SS,

хотя возможна замена сегмента. Во всех остальных случаях адресация по

I умолчанию осуществляется через сегментный регистр DS. Использование

I регистра ЕВР в качестве индексного не адресует нас к стеку: адресация

по-прежнему осуществляется с помощью регистра DS.


 

Глава 4

База + (индекс * масштаб) + смещение
  Нет   Нет  
  ЕАХ   ЕАХ  
  ЕВХ   ЕВХ          
  ЕСХ   ЕСХ       Нет  
  EDX + EDX *   + 8-битовое  
  ESI   ESI   g   32-битовое  
  EDI   EDI   L J    
  ЕВР   ЕВР  
  ESP   я  

Рис. 4.2. Режимы косвенной адресации с использованием 32-разрядных регистров.

Прочерк во второй колонке подчеркивает, что регистр ESP нельзя использовать в качестве индексного. Это не означает, что ESP нельзя ука­зывать в качестве второго операнда:

mov EAX,[ECX][ESP]

Недопустима только конструкция, в которой содержимое ESP умно­
жается на масштабирующий множитель: ^

mov EAX,[ECX][ESP*8] J

fei
Полезно также отметить, что смещение в команде вида ifil

mov EAX,[EBX][ECX]+20 **

может быть только или 8-битовым, или 32-битовым. 16-битовые смеще­ния не образуются. Если указанная в команде величина смещения поме­щается в байт, как это имеет место в приведенном выше примере коман­ды, то смещение в коде команды занимает 1 байт. Если же величина сме­щения больше 255, то под него в коде команды отводится сразу 32 бит.

Таким образом, понятия базовой и индексной адресации в 32-разряд­ных процессорах несколько размываются. Если регистр указывается с мас­штабирующим множителем, то это, конечно, индексная адресация. Если же множитель отсутствует, то адресацию и через ЕВХ, и через ESI с рав­ным успехом можно отнести как к базовой, так и к индексной.

Использование для адресации памяти 16-разрядных регистров резко сужает возможности адресации 32-разрядных процессоров (рис, 4.3). В этом случае мы фактически имеем дело с МП 86.


База

индекс

Г Нет ] Г Нет 1

ВХ + SI

[ ВР J [ D! J


смещение

Нет

8-битовое

16-битовое


Рис. 4.3. Режимы косвенной адресации с использованием 16-разрядных регистров.


Расширенные возможности современных микропроцессоров____________________ 165

Напомним, что в 16-разрядном режиме допустимы не все сочетания базовых и индексных регистров. В качестве базового регистра можно ис­пользовать только ВХ или ВР, а в качестве индексного только SI или DI.

4.3. Использование средств 32-разрядных процессоров в программировании

Как уже отмечалось, при разработке 16-разрядных программ реально­го режима, предназначенных для выполнения по управлением операци­онной системы MS-DOS, вполне допустимо использование ряда допол­нительных возможностей 32-разрядных процессоров. В реальном режиме можно использовать:

32-разрядные операнды;

дополнительные команды и расширенные возможности команд МП 86;

дополнительные режимы адресации;

четыре сегментных регистров для адресации данных вместо двух.

Для того, чтобы транслятор распознавал все эти средства, необходи­мо начать программу с директивы.586 (или, при желании,.486 или.386) и указать при этом для сегментов команд и данных описатель use!6, чтобы программа осталась 16-разрядной.

Следует заметить, что возможности использования в программах ре­ального режима дополнительных средств 32-разрядных процессоров, хотя и кажутся привлекательными, в действительности весьма ограничены. Новых команд не так уж много, и они не имеют принципиального харак­тера; 32-разрядные данные используются в прикладных программах отно­сительно редко (если не касаться вычислительных программ, содержащих действительные числа, но такие программы редко пишут на языке ассем­блера); расширенные возможности адресации в полной мере проявляют­ся лишь в 32-разрядных программах, не работающих в DOS. Тем не менее в каких-то случаях привлечение средств 32-разрядных процессоров может оказаться полезным и в 16-разрядных программах, и мы приведем не­сколько примеров их использования.

Среди системных данных DOS и BIOS есть данные, требующие для своего размещения 2 слов. К таким данным, в частности, относится сис­темное время, накапливаемое в 4х-байтовой ячейке с абсолютным адре­сом 46Ch. Выше, в разделе 3.5, уже описывалась системная процедура отсчета текущего времени. В процессе начальной загрузки компьютера в ячейку с адресом 46Ch переносится из часов реального времени время, истекшее от начала суток, а затем содержимое этой ячейки увеличивает­ся на 1 с каждым прерыванием от системного таймера, подключенного к вектору 8. Чтение ячейки 46Ch позволяет определить текущее время с погрешностью приблизительно в 1/18 секунды, что позволяет достаточно точно измерять интервалы времени. Арифметические действия с систем­ным временем удобно выполнять в расширенных 32-разрядных регистрах.

Рассмотрим программу, которая позволяет установить требуемый вре­менной интервал и отработать некоторым образом его окончание. По­скольку MS-DOS является однозадачной системой, единственным спо­собом организации параллельных процессов — выполнения программы и



Глава 4


ожидания окончания временного интервала — является использование механизма прерываний. В нашем случае программа содержит обработчик прерываний от системного таймера, который 18 раз в секунду читает си­стемное время и сравнивает его значение с заданной заранее величиной. При достижении равенства обработчик прерываний либо сам отрабаты­вает это событие, либо устанавливает флаг окончания временного интер­вала, который периодически тестируется в основной программе. Первый вариант позволяет измерить временной интервал с большей точностью, но второй предоставляет больше возможностей, так как в обработчике прерываний нельзя обращаться к функциям DOS, а основная программа может делать все, что ей заблагорассудится.

Приведенный ниже пример выполнен в виде программы типа.СОМ. Такая организация программы упрощает обработчик прерываний и об­легчает его написание. Дело заключается в том, что процессор, переходя по аппаратному прерыванию на обработчик прерывания, модифицирует только регистры CS:IP (значениями, полученными из вектора прерыва­ний). Все остальные регистры, в том числе и сегментные, сохраняют те значения, которые они имели на момент прерывания. Значения эти могут быть какими угодно, особенно, если основная программа вызывает фун­кции DOS. Поэтому, если в обработчике прерываний необходимо обра­титься к данным, хранящимся в основной программе, нам необходимо настроить какой-либо из сегментных регистров (например, DS или ES) на сегментный адрес сегмента данных основной программы. Если же про­грамма написана в формате.СОМ, то ее поля данных входят в тот же (единственный) сегмент, где расположены команды, и для обращения к данным можно воспользоваться регистром CS, который при вызове обра­ботчика настраивается процессором.

;Пример 4-1. Чтение и сравнение системного времени

;по прерываниям от таймера

.586;Будут 32-разрядные операнды

assume CS:code,DS:code?•

code segment use!6;16-разрядное приложение?.;

org lOOh;Формат.COM Щ

main proc;Сохраним исходный вектор

mov AX,3508h

hit 21h

mov word ptr old_08,BX



Поделиться:




Поиск по сайту

©2015-2024 poisk-ru.ru
Все права принадлежать их авторам. Данный сайт не претендует на авторства, а предоставляет бесплатное использование.
Дата создания страницы: 2016-02-16 Нарушение авторских прав и Нарушение персональных данных


Поиск по сайту: