OberonCore

Библиотека  Wiki  Форум  BlackBox  Компоненты  Проекты
Текущее время: Вторник, 19 Март, 2024 10:10

Часовой пояс: UTC + 3 часа




Начать новую тему Ответить на тему  [ Сообщений: 100 ]  На страницу Пред.  1, 2, 3, 4, 5  След.
Автор Сообщение
 Заголовок сообщения: Re: Оберон-07: вопросы реализации
СообщениеДобавлено: Воскресенье, 24 Февраль, 2019 21:49 
Модератор
Аватара пользователя

Зарегистрирован: Понедельник, 14 Ноябрь, 2005 18:39
Сообщения: 9459
Откуда: Россия, Орёл
Ну такую штуку можно как-то ещё решить окружением.
Например, генерация модуля с такими данными из ресурсного файла.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Оберон-07: вопросы реализации
СообщениеДобавлено: Воскресенье, 24 Февраль, 2019 23:31 
Аватара пользователя

Зарегистрирован: Вторник, 28 Август, 2007 00:55
Сообщения: 518
Откуда: Украина, Днепропетровская обл.
Илья Ермаков писал(а):
Например, генерация модуля с такими данными из ресурсного файла.
И чего будут представлять собой эти данные в коде? Поэлементное присваивание? Тоже UUDecode("Data")? В таком решении сразу три вида потерь памяти: копия в коде, избыток за счёт символьного кодирования, копия в данных. А должна быть только копия в данных.

Кстати, я бы ещё поспорил за присутствие LOOP/EXIT и RETURN из середины процедур. Для мк это может быть ценно хотя бы из соображений производительности.

Господа, я загрустил, поняв, что решить RorLong средствами КП красиво не получится. И родил такое решение:

Код:
   PROCEDURE [code] rorlong (x: LONGINT; n: INTEGER): LONGINT
      059H,                         (* POP    ECX          *)
      083H, 0E1H, 03FH,             (* AND    ECX, 0x3F    *)
      089H, 0C6H,                   (* MOV    ESI, EAX     *)
      089H, 0D7H,                   (* MOV    EDI, EDX     *)
      00FH, 0ADH, 0D6H,             (* SHRD   ESI, EDX, CL *)
      0D3H, 0EFH,                   (* SHR    EDI, CL      *)
      053H,                         (* PUSH   EBX          *)
      031H, 0DBH,                   (* XOR    EBX, EBX     *)
      0F6H, 0C1H, 020H,             (* TEST   CL,  0x20    *)
      00FH, 045H, 0F7H,             (* CMOVNE ESI, EDI     *)
      00FH, 045H, 0FBH,             (* CMOVNE EDI, EBX     *)
      0BBH, 040H, 000H, 000H, 000H, (* MOV    EBX, 0x40    *)
      029H, 0CBH,                   (* SUB    EBX, ECX     *)
      088H, 0D9H,                   (* MOV    CL,  BL      *)
      00FH, 0A5H, 0C2H,             (* SHLD   EDX, EAX, CL *)
      0D3H, 0E0H,                   (* SHL    EAX, CL      *)
      031H, 0DBH,                   (* XOR    EBX, EBX     *)
      0F6H, 0C1H, 020H,             (* TEST   CL,  0x20    *)
      00FH, 045H, 0D0H,             (* CMOVNE EDX, EAX     *)
      00FH, 045H, 0C3H,             (* CMOVNE EAX, EBX     *)
      05BH,                         (* POP    EBX          *)
      00BH, 0C6H,                   (* OR     EAX, ESI     *)
      00BH, 0D7H;                   (* OR     EDX, EDI     *)

   PROCEDURE RorLong* (x: LONGINT; n: INTEGER): LONGINT;
   BEGIN
      ASSERT((0 <= n) & (n <= 63));
      RETURN rorlong(x, n)
   END RorLong;

На этом вопрос снят.

У меня ещё вопрос про реализацию PACK и UNPK. Описание крайне скупое в доках. Как они вообще могут выглядеть в виде алгоритма?


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Оберон-07: вопросы реализации
СообщениеДобавлено: Понедельник, 25 Февраль, 2019 09:35 

Зарегистрирован: Пятница, 20 Июль, 2007 17:26
Сообщения: 710
Откуда: Псков
Oleg N. Cher писал(а):
У меня ещё вопрос про реализацию PACK и UNPK. Описание крайне скупое в доках. Как они вообще могут выглядеть в виде алгоритма?

Не смотрели на IEEE 754, в частности на:
https://ru.wikipedia.org/wiki/%D0%A7%D0 ... 1%82%D0%B8
PS.
Сам-то я, давече, "слегка", на 1 бит, лажанулся про где лежит порядок числа.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Оберон-07: вопросы реализации
СообщениеДобавлено: Вторник, 26 Февраль, 2019 11:33 
Аватара пользователя

Зарегистрирован: Вторник, 28 Август, 2007 00:55
Сообщения: 518
Откуда: Украина, Днепропетровская обл.
Оптимизированный вариант RorLong:
Код:
   PROCEDURE [code] rorlong(x: LONGINT; n: INTEGER): LONGINT
      059H,             (*     POP   ECX          *)
      089H, 0C6H,       (*     MOV   ESI, EAX     *)
      089H, 0D7H,       (*     MOV   EDI, EDX     *)
      00FH, 0ADH, 0D6H, (*     SHRD  ESI, EDX, CL *)
      0D3H, 0EFH,       (*     SHR   EDI, CL      *)
      0F6H, 0C1H, 020H, (*     TEST  CL,  20H     *)
      074H, 002H,       (*     JZ    SHORT L1     *)
      087H, 0F7H,       (*     XCHG  ESI, EDI     *)
      0F6H, 0D9H,       (* L1: NEG   CL           *)
      00FH, 0A5H, 0C2H, (*     SHLD  EDX, EAX, CL *)
      0D3H, 0E0H,       (*     SHL   EAX, CL      *)
      0F6H, 0C1H, 020H, (*     TEST  CL,  20H     *)
      074H, 001H,       (*     JZ    SHORT L2     *)
      092H,             (*     XCHG  EAX, EDX     *)
      00BH, 0C6H,       (* L2: OR    EAX, ESI     *)
      00BH, 0D7H;       (*     OR    EDX, EDI     *)

Коллеги, что скажете насчёт важности контролировать переполнение при логических сдвигах влево? Переполнение в арифметических сдвигах ловить смысл есть. Ofront+ ловит его при константных аргументах, а BlackBox даже в рантайме. В циклических сдвигах переполнений быть не может.

Остаются логические сдвиги. Это не очень понятный момент, но в Обероне-07 такой сдвиг присутствует в языке, то есть, сначала Вирт утверждает, что целый тип — абстрактный, и прикладному программисту не обязательно знать как устроено хранение чисел. Но как только логический сдвиг добавлен в язык — программисту уже требуется знать, что бит знака хранится в старшем разряде, что отрицательные числа хранятся в дополнительном коде и т.д. Получается, выдвинули тезис "числа это не биты", потом радостно его сломали и начали битики двигать. А вот в КП эти сдвиги там, где им и положено быть — в SYSTEM.

Ну да это так, риторика. Но, поскольку я не понимаю смысла присутствия логического сдвига в языке, то ещё труднее мне понять, нужно ли ловить переполнения таких сдвигов? Выскажите, пожалуйста, ваше мнение.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Оберон-07: вопросы реализации
СообщениеДобавлено: Вторник, 26 Февраль, 2019 11:43 

Зарегистрирован: Понедельник, 28 Ноябрь, 2005 10:28
Сообщения: 1428
А зачем делать сдвиги для LONGINT? Этого же нет в языке, да и смысла в них особо нет.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Оберон-07: вопросы реализации
СообщениеДобавлено: Вторник, 26 Февраль, 2019 11:45 
Аватара пользователя

Зарегистрирован: Вторник, 28 Август, 2007 00:55
Сообщения: 518
Откуда: Украина, Днепропетровская обл.
Мне даже в Обероне-07 нужна поддержка типа SYSTEM.ADRINT, а он может быть 64-битным.

Любой реализатор Оберона-07 сталкивается с тем, что ему предлагают накрепко привязать разрядность адресного типа к INTEGER. Я не считаю, что это такая уж хорошая идея. Поэтому INTEGER отдельно, SYSTEM.ADRINT отдельно.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Оберон-07: вопросы реализации
СообщениеДобавлено: Вторник, 26 Февраль, 2019 13:20 

Зарегистрирован: Четверг, 08 Май, 2008 19:13
Сообщения: 1447
Откуда: Киев
Oleg N. Cher писал(а):
Мне даже в Обероне-07 нужна поддержка типа SYSTEM.ADRINT, а он может быть 64-битным.
И биты вращать адресу тоже нужно? Вы, ведь, знаете, что в общем случае адрес - это не обязательно индекс в массиве общей памяти?


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Оберон-07: вопросы реализации
СообщениеДобавлено: Вторник, 26 Февраль, 2019 14:15 

Зарегистрирован: Понедельник, 28 Ноябрь, 2005 10:28
Сообщения: 1428
Если адрес 64-битный, то и процессор, скорее всего, тоже. Но тогда реализация сдвигов довольно проста.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Оберон-07: вопросы реализации
СообщениеДобавлено: Вторник, 26 Февраль, 2019 14:47 
Аватара пользователя

Зарегистрирован: Вторник, 28 Август, 2007 00:55
Сообщения: 518
Откуда: Украина, Днепропетровская обл.
Хорошо, я попробую иначе сформулировать. Мне нужна единая разрядность INTEGER на 32-х и 64-битных архитектурах, чтобы писать код без оглядки на разрядность системы. С той же целью нужна единостильная работа с адресами через тип SYSTEM.ADRINT. Посему да, поддержку сдвигов для 64-х бит нужно заложить, она тут сама просится. Также нужна возможность даже из Оберона-07 работать с системным типом SYSTEM.INT64.

Ещё я не исключаю возможность опционально задавать для Оберона-07 разрядность INTEGER.

А ещё я делаю реализацию Ofront+ для BlackBox, а он чисто 32-битный, как вы знаете. На самом Ofront+ с циклическими сдвигами проблем вообще нет — ROR сделан через SYSTEM.ROT.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Оберон-07: вопросы реализации
СообщениеДобавлено: Среда, 27 Февраль, 2019 06:37 

Зарегистрирован: Вторник, 26 Январь, 2010 09:31
Сообщения: 717
Откуда: Барнаул
В А2 есть реализации, и в них есть ссылка на хороший папир
Код:
PROCEDURE RorH*(l: HUGEINT; r: LONGINT): HUGEINT;
CODE{SYSTEM.i386}
   PUSH   ECX
   ; taken from "Software Optimization Guide for AMD64 Processors"
   MOV ECX,[EBP+r+0]
   MOV EAX,[EBP+l+0]
   MOV EDX,[EBP+l+4]
   ; EBX (initially=EAX) -> EDX -> EAX
   ; Shift EDX:EAX right, shift count in ECX (count
   ; applied modulo 64).
   MOV EBX,EAX
   SHRD EAX,EDX,CL      ; First apply shift count.
   SHRD EDX,EBX,CL       ; mod 32 to EDX:EAX
   TEST ECX,32          ; Need to shift by another 32?
   JZ rshiftdone          ; No, done.
   MOV EBX,EAX
   SHRD EAX,EDX,CL
   SHRD EDX,EBX,CL
   rshiftdone:
   POP   ECX
END RorH;

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


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Оберон-07: вопросы реализации
СообщениеДобавлено: Среда, 27 Февраль, 2019 12:30 
Аватара пользователя

Зарегистрирован: Вторник, 28 Август, 2007 00:55
Сообщения: 518
Откуда: Украина, Днепропетровская обл.
Переписал для BlackBox:
Код:
   PROCEDURE [code] rorlong(x: LONGINT; n: INTEGER): LONGINT
      (* taken from "Software Optimization Guide for AMD64 Processors"           *)
      (* ESI (initially=EAX) -> EDX -> EAX                                       *)
      (* Shift EDX:EAX right, shift count in ECX (count applied modulo 64).      *)
   059H,             (*      POP   ECX           *)
   08BH, 0F0H,       (*      MOV   ESI, EAX      *)
   00FH, 0ADH, 0D0H, (*      SHRD  EAX, EDX, CL  ; First apply shift count.     *)
   00FH, 0ADH, 0F2H, (*      SHRD  EDX, ESI, CL  ; mod 32 to EDX:EAX            *)
   0F6H, 0C1H, 020H, (*      TEST  CL,  32       ; Need to shift by another 32? *)
   074H, 008H,       (*      JZ    SHORT done    ; No, done.                    *)
   08BH, 0F0H,       (*      MOV   ESI, EAX      *)
   00FH, 0ADH, 0D0H, (*      SHRD  EAX, EDX, CL  *)
   00FH, 0ADH, 0F2H  (*      SHRD  EDX, ESI, CL  *)
   ;                 (* done:                    *)

Код точно рабочий? Я проверил. Он даёт для ROR(1, 1) результат F333333333333334, для ROR(1, 2) то же самое.

Kemet писал(а):
Контролировать переполнение смысла нет, так как такого контроля нет и в арифметических операциях
В Ofront'е+ при вычислении константных значений такой контроль есть. А в BlackBox он встречается и в рантайме (в ASH, в частности).


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Оберон-07: вопросы реализации
СообщениеДобавлено: Среда, 27 Февраль, 2019 14:15 

Зарегистрирован: Вторник, 26 Январь, 2010 09:31
Сообщения: 717
Откуда: Барнаул
А как в ББ параметры передаются?


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Оберон-07: вопросы реализации
СообщениеДобавлено: Среда, 27 Февраль, 2019 14:31 

Зарегистрирован: Вторник, 26 Январь, 2010 09:31
Сообщения: 717
Откуда: Барнаул
Oleg N. Cher писал(а):
Код точно рабочий? Я проверил. Он даёт для ROR(1, 1) результат F333333333333334, для ROR(1, 2) то же самое.

Рабочий
Код:
PROCEDURE Do*;
VAR x: HUGEINT;
BEGIN
    x := 1;
    TRACE( SYSTEM.VAL( SET64, x  ));
    x := ROR( x, 1);
    TRACE( SYSTEM.VAL( SET64, x  ));
    x := ROR( x, 1);
    TRACE( SYSTEM.VAL( SET64, x  ));
    x := ROR( x, 1);
    TRACE( SYSTEM.VAL( SET64, x  ));

    x :=1;
    x := ROR( x, 3);
    TRACE( SYSTEM.VAL( SET64, x  ));
END Do;

Вывод
{P cpuid= 0, pid= 9360 Test.Do@84:SYSTEM.VAL(SET64, x)= {0}; }
{P cpuid= 0, pid= 9360 Test.Do@136:SYSTEM.VAL(SET64, x)= {63}; }
{P cpuid= 0, pid= 9360 Test.Do@188:SYSTEM.VAL(SET64, x)= {62}; }
{P cpuid= 0, pid= 9360 Test.Do@240:SYSTEM.VAL(SET64, x)= {61}; }
{P cpuid= 0, pid= 9360 Test.Do@302:SYSTEM.VAL(SET64, x)= {61}; }


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Оберон-07: вопросы реализации
СообщениеДобавлено: Среда, 27 Февраль, 2019 15:48 
Аватара пользователя

Зарегистрирован: Вторник, 28 Август, 2007 00:55
Сообщения: 518
Откуда: Украина, Днепропетровская обл.
Kemet писал(а):
А как в ББ параметры передаются?
Цитата:
Процедуры в машинных кодах позволяют использовать специальные последова­тель­ности машинных команд, которые не генерируются компилятором. Для их объявления исполь­зуется следующий специальный синтаксис:

ProcDecl = PROCEDURE "[" SysFlag "]" IdentDef [FormalPars]
[ConstExpr {"," ConstExpr}] ";".

Список констант, объявленный с процедурой, интерпретируется как строка байт и встав­ляется непосредственно в код («in-line»), из которого вызвана процедура. Если присут­ствует список параметров, фактические параметры загружаются в стек справа налево. Однако первый параметр записывается в регистр. Если тип первого параметра REAL или SHORTREAL, то он записывается в верхний регистр для чисел с плавающей точкой. Иначе параметр (или в случае VAR/IN/OUT-параметра — его адрес) записывается в EAX. Для процедур-функций ожидается, что и результат сохраняется в верхнем регистре с плавающей точкой или в EAX, в зависимости от его типа. Будьте осторожны, когда используете регистры в кодовых процедурах. В общем, можно использовать регистры ECX, EDX, ESI и EDI. Параметры должны удаляться со стека процедурой.

Примеры

PROCEDURE [code] Sqrt (x: REAL): REAL (* Math.Sqrt *)
0D9H, 0FAH; (* FSQRT *)

PROCEDURE [code] Erase (adr, words: INTEGER) (* erase memory area *)
089H, 0C7H, (* MOV EDI, EAX *)
031H, 0C0H, (* XOR EAX, EAX *)
059H, (* POP ECX *)
0F2H, 0ABH; (* REP STOS *)

Для нашего случая

PROCEDURE {code} rorlong (x: LONGINT; n: INTEGER): LONGINT;

аргумент x передаётся в EDX:EAX, аргумент n мы снимаем со стека командой POP ECX, а результат ожидается в EDX:EAX.

Также в варианте для BlackBox я использовал регистр ESI вместо EBX, потому что EBX нужно было бы сохранять, а ESI не надо.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Оберон-07: вопросы реализации
СообщениеДобавлено: Среда, 27 Февраль, 2019 17:43 
Аватара пользователя

Зарегистрирован: Вторник, 28 Август, 2007 00:55
Сообщения: 518
Откуда: Украина, Днепропетровская обл.
Kemet, этот код точно нерабочий для n >= 32, можете подавать баг-репорт.

Смотрите. Если первый сдвиг производится на (n mod 32) битов, а там нужен был сдвиг на {0..63}, то второй сдвиг надо делать ровно на 32 бита, т.е. просто поменять регистры местами. А он опять делается на (n mod 32) битов.

Вот рабочий вариант:
Код:
   PROCEDURE [code] rorlong(x: LONGINT; n: INTEGER): LONGINT
      059H,             (*      POP   ECX           *)
      08BH, 0F0H,       (*      MOV   ESI, EAX      *)
      00FH, 0ADH, 0D0H, (*      SHRD  EAX, EDX, CL  *)
      00FH, 0ADH, 0F2H, (*      SHRD  EDX, ESI, CL  *)
      0F6H, 0C1H, 020H, (*      TEST  CL,  32       *)
      074H, 001H,       (*      JZ    SHORT done    *)
      092H              (*      XCHG  EAX, EDX      *)
   ;                    (* done:                    *)


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Оберон-07: вопросы реализации
СообщениеДобавлено: Четверг, 28 Февраль, 2019 06:15 

Зарегистрирован: Вторник, 26 Январь, 2010 09:31
Сообщения: 717
Откуда: Барнаул
XCHG там не подходит, потому что не устанавливает флаги, которые устанавливаются в 64-битном режиме.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Оберон-07: вопросы реализации
СообщениеДобавлено: Четверг, 28 Февраль, 2019 07:51 
Аватара пользователя

Зарегистрирован: Вторник, 28 Август, 2007 00:55
Сообщения: 518
Откуда: Украина, Днепропетровская обл.
Очень даже подходит. Зачем нужно устанавливать эти флаги? Кто-то после вызова процедуры будет полагаться на них? Может есть негласные правила, как их надо выставить правильно? Бред же.

Коллеги, кто может прояснить вопрос: зачем BlackBox требует сохранять регистр общего назначения EBX? Как именно он его использует? Я предполагаю, что в документации просто забыли упомянуть EBX как разрешённый для изменения регистр.

Oleg N. Cher писал(а):
Код точно рабочий? Я проверил. Он даёт для ROR(1, 1) результат F333333333333334
А вот это, оказывается, было вызвано багом в калькуляторе Windows 7. Попробуйте вставить число -9223372036854775808 и сконвертить в Hex 8 байт. Он выдаёт: F333333333333334. Если вбить в Hex вручную 8000000000000000 и сконвертить обратно в Dec, будет -9223372036854775808. Мда уж.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Оберон-07: вопросы реализации
СообщениеДобавлено: Пятница, 01 Март, 2019 07:06 
Аватара пользователя

Зарегистрирован: Воскресенье, 09 Декабрь, 2018 15:14
Сообщения: 113
Откуда: Equestria
Oleg N. Cher писал(а):
Коллеги, кто может прояснить вопрос: зачем BlackBox требует сохранять регистр общего назначения EBX? Как именно он его использует? Я предполагаю, что в документации просто забыли упомянуть EBX как разрешённый для изменения регистр.

Он используется как статическая свзязь. Т.е. используются локальными процедурами.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Оберон-07: вопросы реализации
СообщениеДобавлено: Суббота, 02 Март, 2019 17:44 

Зарегистрирован: Вторник, 26 Январь, 2010 09:31
Сообщения: 717
Откуда: Барнаул
Oleg N. Cher писал(а):
Очень даже подходит.
Всё-же, я думаю, что после XCHG нужно поставить что-то типа
Код:
TEST EDX, 80000000H
JZ done
STC


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Оберон-07: вопросы реализации
СообщениеДобавлено: Воскресенье, 03 Март, 2019 11:17 
Аватара пользователя

Зарегистрирован: Вторник, 28 Август, 2007 00:55
Сообщения: 518
Откуда: Украина, Днепропетровская обл.
Зачем? Вам так спокойнее? :-)

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

Kemet, но чисто для Вас я поменял местами XCHG и SHRD.
Код:
   PROCEDURE [code] rorlong (x: LONGINT; n: INTEGER): LONGINT
      059H,             (*     POP  ECX          *)
      0F6H, 0C1H, 020H, (*     TEST CL, 32       *)
      074H, 001H,       (*     JZ   SHORT L1     *)
      092H,             (*     XCHG EAX, EDX     *)
      08BH, 0F0H,       (* L1: MOV  ESI, EAX     *)
      00FH, 0ADH, 0D0H, (*     SHRD EAX, EDX, CL *)
      00FH, 0ADH, 0F2H; (*     SHRD EDX, ESI, CL *)


Вернуться к началу
 Профиль  
 
Показать сообщения за:  Поле сортировки  
Начать новую тему Ответить на тему  [ Сообщений: 100 ]  На страницу Пред.  1, 2, 3, 4, 5  След.

Часовой пояс: UTC + 3 часа


Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 1


Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете добавлять вложения

Найти:
Вся информация, размещаемая участниками на конференции (тексты сообщений, вложения и пр.) © 2005-2024, участники конференции «OberonCore», если специально не оговорено иное.
Администрация не несет ответственности за мнения, стиль и достоверность высказываний участников, равно как и за безопасность материалов, предоставляемых участниками во вложениях.
Без разрешения участников и ссылки на конференцию «OberonCore» любое воспроизведение и/или копирование высказываний полностью и/или по частям запрещено.
Powered by phpBB® Forum Software © phpBB Group
Русская поддержка phpBB