На главную Наши проекты:
Журнал   ·   Discuz!ML   ·   Wiki   ·   DRKB   ·   Помощь проекту
ПРАВИЛА FAQ Помощь Участники Календарь Избранное RSS
msm.ru
! Перед отправкой сообщения внимательно прочтите правила раздела!!!
1. Запрещается обсуждать написание вирусов, троянов и других вредоносных программ!
2. Помните, что у нас есть FAQ раздела Assembler и Полезные ссылки. Посмотрите, возможно, там уже имеется решение вашего вопроса.

3. Настоятельно рекомендуем обратить особое внимание на правила форума, которые нарушаются чаще всего:
  3.1. Заголовок темы должен кратко отражать её суть. Темы с заголовками типа "Срочно помогите!" или "Ассемблер" будут отправляться в Корзину для мусора.
  3.2. Исходники программ обязательно выделяйте тегами [code]...[/code] (одиночные инструкции можно не выделять).
  3.3. Нежелательно поднимать старые темы (не обновлявшиеся более года) без веской на то причины.

Не забывайте также про главные Правила форума!

Добро пожаловать и приятного вам общения!!! ;)
 
Модераторы: Jin X, Qraizer
  
> Макросы TASM
    Написал вот такой макрос:
    ExpandedWrap disabled
      __defdef macro const,value
        ifndef const
          const = value
        endif
      endm
    Макрос определяет константу, если она не была определена ранее.
    Однако есть проблема: компилер выдаёт warning, что "Module is pass depending". Как от этого избавиться?

    Вообще, есть где-нибудь нормальный мануал по макросам в TASM/MASM ?
    Ищу, не могу найти ничего...

    И ещё, можно ли как-то определить: используется ли та или иная процедура в коде или нет? Чтобы написать include с несколькими процедурами, а в код включать только те, которые реально используются.

    Кстати, как проверить - какой ассемблер используется: TASM, MASM или FASM ?
    Может, какие-то символы определены для этого?
      Комментарий в pow.asm намекает:
      ExpandedWrap disabled
        if 1 ; was ifdef MASM, but TASM for OS/2 has a bug here as well
      что есть (были) определения "MASM"/"TASM". :unsure:

      Добавлено
      Да, и такое встретилось:
      ExpandedWrap disabled
        ifndef MASM
                        .model  FLAT
        endif
        Славян, скинь весь этот pow.asm, плиз, возможно там где-то эти символы определяются. Потому что ни TASM, ни MASM не работает.
          Цитата Jin X @
          возможно там где-то эти символы определяются.
          Нету, только разве что здесь (оттуда же строки), что тоже маловероятно:
          ExpandedWrap disabled
                    include RULES.ASI
                    include _MATH.INC
          А вообще это стандартный файл из Borland'овской RAD-XEn (\source\cpprtl\Source\math\pow.asm), где n у меня = 3 или 8.

          Только что просмотрел этот RULES.ASI, нету там. Думаю, что это среда определяет, коя компилирует. Т.е. микрософтовцы - MASM, а борланды - TASM. :unsure:
            Цитата Jin X @
            Однако есть проблема: компилер выдаёт warning, что "Module is pass depending". Как от этого избавиться?

            Если в теле этой директивы определяется идентификатор, то автоматом выполняется проход в режиме совместимости MASM, отключается оптимизация и выдается это предупреждение. Ее можно отключить либо директивой NOWARN, либо параметром командной строки /W-. Однако, в этом случае отключаются вообще все предупреждения, включая некоторые полезные. Я бы не рисковал, уж лучше просто игнорировать это предупреждение, код то все равно будет сгенерирован правильный (только без оптимизации).

            Конструкция IFDEF/IFNDEF предназначена для других целей, не зависящих от прохода. Например:
            ExpandedWrap disabled
              ifdef UNICODE
                  typedef TCHAR WORD
                  ....
                  AddDesktopItem                   equ <AddDesktopItemW>
              else
                  typedef TCHAR BYTE
                  ....
                  AddDesktopItem                   equ <AddDesktopItemA>
              endif

            В этом случае все будет Ок.

            Цитата Jin X @
            И ещё, можно ли как-то определить: используется ли та или иная процедура в коде или нет? Чтобы написать include с несколькими процедурами, а в код включать только те, которые реально используются.
            Нет, как и в Сях включения кода нужно контролировать самому. Либо через условные директивы, либо оформляя функции в отдельные модули (чтобы включать только нужные, а не все скопом). Собственно RTL у BC тоже разбито на множество модулей - по одной функции на модуль (это и позволяет включать только реально используемые).
            Ну или использовать условную компиляцию:
            ExpandedWrap disabled
              ifdef XXXX
                procdesc YYYY @@par1:word, @@par2:byte
                
                proc YYYY uses ds, @@p1: word, @@p2: byte
                ...
                endp
              endif
               
              ...
               
              XXXX = 1
              call YYYY, ax, bx


            Цитата Jin X @
            Кстати, как проверить - какой ассемблер используется: TASM, MASM или FASM ?
            А в чем смысл? Отличия настолько велики, что все равно не учтешь.
            Но, если уж так приспичило, то можно по предопределенным идентификаторам. Например так:
            ExpandedWrap disabled
              ifdef ??version
                MSG equ <"USE TASM",0>
              else
                MSG equ <"USE MASM",0>
              endif

            За fasm не скажу, понятия не имею что у него предопределено и есть ли в нем вообще такие фичи.

            Добавлено
            Цитата Jin X @
            Вообще, есть где-нибудь нормальный мануал по макросам в TASM/MASM ?
            Ищу, не могу найти ничего...

            В сети есть Turbo Assembler 5.0 Users Guide. Можно взять еще Paradigm Assembler. Тот же турбо, видимо прикупали лицензию.
            Если не нагуглишь, пиши, выложу.

            Добавлено
            Кстати, тов. модератор, нельзя ли мне разрешить подписку на темы?
              По warning'у, в общем, я решил вместо if использовать в коде ifdef и не ставить дефолтовых значений. А где надо число - там ввожу дополнительную переменную, значение которой уж задаётся в зависимости от того, была задана константа до include'а или нет...

              Цитата Eretic @
              Ну или использовать условную компиляцию:
              Ну, это-то понятно. Но это не то.

              Цитата Eretic @
              А в чем смысл? Отличия настолько велики, что все равно не учтешь.
              Да, ??Version я тоже нашёл, для MASM есть @Version ;)

              Цитата Eretic @
              В сети есть Turbo Assembler 5.0 Users Guide.
              English?

              Цитата Eretic @
              Кстати, тов. модератор, нельзя ли мне разрешить подписку на темы?
              Ты хочешь подписываться на темы? А какие проблемы, разве у тебя такой функции нет? Избранное ещё...
                Цитата Jin X @
                Да, ??Version я тоже нашёл, для MASM есть @Version
                Именно. Вот по таким ерундовинам и можно точно определять откуда компилируемся.

                Цитата Jin X @
                English?
                К сожалению. Из русского есть только переведенные маны на TASM 3.0. Не ахти конечно и довольно кратко изложено, зато некоторые вещи разжеваны от и до. В сети инфа в основном из этих манов. Собственно разница с 5.0 небольшая и макроязык изменился не очень сильно. Добавились новые флаги во встроенные переменные (@cpu и тд) и команды псевдоЯВУ - .if, .while и тд.
                Еще есть Том Свен - Освоение Turbo Assembler. Но там по макросам тоже не ахти, только самые основы, без углубления в тонкости.

                Могу в качестве подспорья предложить архивчик чьего-то творения - TASM-Macro-Language-2.0. Сам не пользовался, поскольку к моменту его появления уже отошел от тасма, но примерчики доставляют:
                ExpandedWrap disabled
                  Include "system.h"
                   
                  Program SwitchDemo3;
                  Var
                     char key;
                  Begin
                     WriteLn<'Press f,e,h or any key.'>;
                     ReadKey = key;
                     switch <key>;
                       case 'f'  :  <WriteLn<'File.'>>;
                       case 'e'  :  <WriteLn<'Edit.'>>;
                       case 'h'  :  <WriteLn<'Help.'>>;
                       default   :  <WriteLn<'Macro Language!'>>;
                     endswitch;
                  End_

                ExpandedWrap disabled
                  Include "system.h"
                   
                  Program MacroDemo4;
                  Var
                     words IBM, PC;
                  macro Move a,b;
                        GetSymbolSize a;
                        if (@_SymbolSize NE 0)
                           mov [a],b;
                        else
                           GetSymbolSize b;
                           if (@_SymbolSize NE 0)
                              mov a,[b];
                           else
                              mov a,b;
                           endif;
                        endif;
                  endm;
                   
                  Begin
                     Move IBM,123;
                     WriteLn<'IBM = '>,IBM;
                     Move ax,456;
                     Move bx,IBM;
                     Move PC,bx;
                     Move IBM,ax;
                     WriteLn<'IBM = '>,IBM;
                     WriteLn<'PC = '>,PC;
                  End_

                Кто-то очень серьезно подошел к процессу творчества :)

                Собственно тоже когда-то занимался подобным "макротворчеством". Помнится пришлось помучиться с символами < и >, поскольку они в макросах имеют особое значение, но в итоге победил и получилось почти не отличимо от оригинала:
                ExpandedWrap disabled
                  ;+-------------------------------------------------------------------------+
                  ;|                                 ЦИКЛЫ                                   |
                  ;+-------------------------------------------------------------------------+
                  $COLN FOR_    ; ( nh nl -- )    for i := nl to nh-1
                          _       R> DUP @ >R     ; для BREAK
                          _       ROT >R          ; граничное (nh)
                          _       SWAP >R         ; начальное (nl)
                          _       CELL+ >R EXIT   ; обойти адрес в шитом коде
                   
                   
                  $COLN NEXT_   ;                 next i
                          _       R> R> R@        ; возврат текущее граничное
                          _       - 1+ DUP 0=
                          _       IF DROP R> R> 2DROP CELL+
                          _       ELSE R@ + >R @
                          _       ENDIF >R
                          _       EXIT
                   
                  $COLN I       ; ( -- n )              ложит на стек счетчик цикла
                          _       R> R@ SWAP >R EXIT
                   
                  $COLN BREAK
                          _       R> DROP R> DROP R> DROP EXIT
                   
                  ;+-------------------------------------------------------------------------+
                  ;|                            ОПЕРАЦИИ СРАВНЕНИЯ                           |
                  ;+-------------------------------------------------------------------------+
                  ; для любых чисел
                  $COLN =       ; ( x1 x2 -- f )        if (x1 == x2) f=TRUE else f=FALSE
                          _       XOR IF FALSE ELSE TRUE ENDIF EXIT
                   
                  $COLN 0=      ; ( x -- f )            if (x = 0) f=TRUE else f=FALSE
                          _       0 = EXIT
                   
                  ; для чисел со знаком
                  $COLN 0<      ; ( n -- f )            if (n < 0) f=TRUE else f=FALSE
                          _       15 SHR 1- NOT EXIT
                   
                  $COLN <<      ; ( n1 n2 -- f )        if (n1 <  n2) f=TRUE else f=FALSE
                          _       2DUP XOR 0< IF DROP ELSE - ENDIF 0< EXIT
                   
                  $COLN >       ; ( n1 n2 -- f )        if (n1 >  n2) f=TRUE else f=FALSE
                          _       2DUP = ROT ROT < OR NOT EXIT
                   
                  ; для беззнаковых чисел
                  $COLN U<      ; ( u1 u2 -- f )        if (u1 <  u2) f=TRUE else f=FALSE
                          _       2DUP XOR 0< IF SWAP DROP ELSE - ENDIF 0< EXIT
                   
                  ; числа двойной точности
                  $COLN D0=     ; ( d -- f )            if ( d == 0 ) f=TRUE else f=FALSE
                          _       0= SWAP 0= AND EXIT
                   
                  ;+-------------------------------------------------------------------------+
                  ;|                            ФОРМАТНЫЙ ВЫВОД                              |
                  ;+-------------------------------------------------------------------------+
                  VARIABLE PAD, 128                     ; буфер для форматного ввода/вывода
                  VARIABLE HLD                          ; текущая позиция в PAD
                   
                  $COLN DIGIT   ; ( u -- c )            число в символ
                          _       9 OVER < 7 AND + '0' + EXIT
                   
                  $COLN HOLD    ; ( c -- )              заносит символ в буфер PAD
                          _       HLD @ 1- DUP HLD ! C! EXIT
                   
                  $COLN <<#     ; ( -- )                начало форматного преобразования числа
                          _       PAD 126 + HLD ! EXIT  ; установка указателя в конец буфера PAD
                   
                  $COLN #>      ; ( d -- a n )          конец форматного преобразования
                          _       2DROP HLD @ PAD 126 + OVER - EXIT
                   
                  $COLN #       ; ( ud -- ud )          заносит в PAD один символ от числа (по BASE)
                          _       OVER BASE @ U>=
                          _       IF
                          _           0 ROT BASE @ UM/MOD
                          _       ELSE
                          _           SWAP 0
                          _       ENDIF
                          _       >R SWAP BASE @ UM/MOD R> ROT
                          _       DIGIT HOLD SWAP EXIT
                   
                  $COLN #S      ; ( d -- 0 0 )          полное преобразование числа в строку
                          _       BEGIN # 2DUP D0= UNTIL EXIT
                   
                  $COLN SIGN    ; ( n -- )              ложит в буфер PAD знак числа, если оно отрицательное
                          _       0< IF 45 HOLD ENDIF EXIT
                   
                  ;+-------------------------------------------------------------------------+
                  ;|                          ОПЕРАЦИИ ПРЕОБРАЗОВАНИЯ                        |
                  ;+-------------------------------------------------------------------------+
                  $COLN D.      ; ( d -- )              вывод знакового двойного числа
                          _       OVER SWAP DABS <# #S ROT SIGN #> TYPE EXIT
                   
                  $COLN UD.     ; ( ud -- )             вывод беззнакового двойного числа
                          _       <<# #S
                          _       #> TYPE EXIT
                   
                  $COLN D.R     ; ( d fn -- )           вывод знакового двойного числа с выравниванием по правому краю
                          _       2 PICK 2SWAP DABS <# #S ROT SIGN #> ROT OVER - DUP >0
                          _       IF SPACES ELSE DROP ENDIF
                          _       TYPE EXIT
                   
                  $COLN UD.R    ; ( ud fn -- )          вывод беззнакового двойного числа с выравниванием по правому краю
                          _       ROT ROT <# #S #> ROT OVER - DUP >0
                          _       IF SPACES ELSE DROP ENDIF
                          _       TYPE EXIT
                   
                  $COLN .       ; ( n -- )              вывод знакового числа
                          _       N>D D. EXIT
                   
                  $COLN U.      ; ( u -- )              вывод беззнакового числа
                          _       U>D UD. EXIT
                   
                   
                  $COLN .R      ; ( n -- )              вывод знакового числа с выравниванием по правому краю
                          _       N>D D.R EXIT
                   
                  $COLN U.R     ; ( u -- )              вывод беззнакового числа с выравниванием по правому краю
                          _       U>D UD.R EXIT

                Любители Форта оценят ;)

                Добавлено
                Цитата Jin X @
                Ты хочешь подписываться на темы? А какие проблемы, разве у тебя такой функции нет? Избранное ещё...

                У меня мыло было просроченным и форум автоматом отключил возможность подписки на темы, т.к. ответы слать было некуда. Сейчас поменял на новое, но теперь нужно кому-то ручками разрешить подписку на темы.
                  Цитата Eretic @
                  Еще есть Том Свен - Освоение Turbo Assembler. Но там по макросам тоже не ахти, только самые основы, без углубления в тонкости.
                  Смысла изучать отдельно особенности TASM сейчас мало. Либо MASM или какой-то совмещённый мануал (т.к. по сути, там всё почти одно и то же), либо FASM. ИМХО.
                  А новые инструкции - по мануалам интела.

                  Цитата Eretic @
                  Могу в качестве подспорья предложить архивчик чьего-то творения - TASM-Macro-Language-2.0.
                  Ну прям паскаль, даже ";" в конце :lol: . А где system.h?

                  Цитата Eretic @
                  Собственно тоже когда-то занимался подобным "макротворчеством". Помнится пришлось помучиться с символами < и >, поскольку они в макросах имеют особое значение, но в итоге победил и получилось почти не отличимо от оригинала
                  Что-то не пойму, это какой ассемблер? Явно не TASM/MASM/FASM.

                  Цитата Eretic @
                  теперь нужно кому-то ручками разрешить подписку на темы
                  Т.е. ссылка "Подписаться на тему" не срабатывает?
                  Или Мой профиль -> Настройки e-mail -> "Включить 'E-mail Уведомление' по умолчанию?" не пашет? Тогда нужно тему создать вот тут: Книга жалоб и предложений
                    Цитата Jin X @
                    Что-то не пойму, это какой ассемблер? Явно не TASM/MASM/FASM.

                    Самый натуральный TASM, использовался мной для защиты загрузчика CD-диска от всяких прыщавых недорослей (разобраться в шитом коде - это далеко не всякий сможет). Вот набросал примерчик, вывод дампа PSP:
                    ExpandedWrap disabled
                              p286
                              ideal
                              model   tiny
                              locals  @@
                       
                      ; размеры стэков форт-системы
                        ARITH_STACK_SIZE      = 1024
                        RET_STACK_SIZE        = 1024
                       
                       
                       
                       
                       
                      codeseg
                      ;        org 0
                              org     100h
                        Start:
                              cli
                      ;        ; корректируем адрес размещения программы в памяти
                      ;        push    7c0h
                      ;        push    offset Init
                      ;        retf                    ; теперь код гарантированно по адресу 7C0:0000
                      ;  Init:
                              mov     ax, cs
                              mov     ds, ax
                              mov     es, ax
                              mov     ss, ax          ; cs=es=ds=ss - модель на один 64 Кб сегмент
                              ; готовим стэки для форт-системы
                              mov     ax, offset END_CODE
                              inc     ax
                              and     al, not 1
                              add     ax, ARITH_STACK_SIZE
                              mov     sp, ax          ; sp - арифметический стэк
                              add     ax, RET_STACK_SIZE
                              mov     bp, ax          ; bp - стэк возвратов
                              sti
                              ; переходим на шитый код форт-системы
                              call    _FORT
                       
                      include "core.inc"
                      include "coreext.inc"
                       
                      VARIABLE HALTADDR               ; адрес возврата из Форта
                       
                      $CODE WAIT
                              xor     ax, ax
                              int     16h
                              $NEXT
                       
                      $CODE HALT
                              mov     ax, 4C00h
                              int     21h
                       
                      VARIABLE R0
                      VARIABLE S0
                       
                      $COLN SYS-INIT  ;               настройка форта
                            _         RP@ R0 !        ; сохраняем адрес верхушки стэка возвратов
                            _         SP@ S0 !        ; сохраняем адрес верхушки арифметического стэка
                            _         DECIMAL
                            _         7h ATR !        ; атрибут для вывода символов
                            _         EXIT
                       
                      $COLN DEPTH ; ( -- n )          выводит кол. слов на ариф. стэке
                            _         SP@ S0 @ SWAP - 1 SHR EXIT
                       
                       
                       
                      ;=============================================================================
                      ;                               точка входа в Форт
                      ;=============================================================================
                      ; на входе:
                      ;       sp      - арифметический стэк
                      ;       bp      - стэк возвратов
                      ; на ариф. стэке:
                      ;       [sp-2]  - текущий дисковод
                      ;       [sp]    - адрес возврата из форт-системы
                      $COLN FORT
                      _       HALTADDR !              ;; сохраняем адрес возврата
                      _       SYS-INIT
                       
                      _       0h 16 DUMP              ; вводим дамп PSP
                       
                      _       CR DEPTH
                      _       WAIT HALT
                       
                      ;=============================================================================
                      $COLN #CA                       ; уст. цвет строки адреса
                            _         31h ATR ! EXIT
                      $COLN #HEX                      ; уст. цвет строки шестнадцатеричного дампа
                            _         1Fh ATR ! EXIT
                      $COLN #CHAR                     ; уст. цвет строки символов
                            _         70h ATR ! EXIT
                       
                      $COLN DUMP    ; ( a nlines -- ) вывод содержимого ряда адресов памяти
                      _     CR BASE @ >R HEX                ; сохраняем текущую базу счисления и устанавливаем шестнадцатеричную
                      _     HEX
                      _     0 FOR
                      _       #CA DUP 0 SWAP <# # # # # #> TYPE 58 EMIT
                      _       #HEX 16 0 FOR
                      _         I 4 MOD 0= IF SPACE ENDIF   ; группируем по 4 байта
                      _         DUP I + C@ 0 SWAP
                      _         <# # # #> TYPE SPACE
                      _       NEXT
                      _       #CHAR 16 0 FOR
                      _         I 4 MOD 0= IF SPACE ENDIF   ; группируем по 4 символа
                      _         DUP I + C@ DUP
                      _         BL >= OVER 240 < AND NOT    ; печатный символ ASCII?
                      _         IF DROP 46 ENDIF EMIT
                      _       NEXT
                      _       16 + CR
                      _     NEXT
                      _     DROP
                      _     R> BASE !                       ; восстанавливаем базу счисления
                      _     EXIT
                       
                       
                      END_CODE:
                      end Start

                    Результат:
                    user posted image


                    Прикреплённый файлПрикреплённый файлFORT.zip (1,45 Кбайт, скачиваний: 158)

                    Добавлено
                    Цитата Jin X @
                    Смысла изучать отдельно особенности TASM сейчас мало. Либо MASM или какой-то совмещённый мануал (т.к. по сути, там всё почти одно и то же), либо FASM. ИМХО.

                    Макросы TASM почти один в один как и у MASM. Пожалуй единственное существенное отличие - в MASM ввели макросы-функции, то есть макросы возвращающие результат. В принципе легко обходится, просто так иногда удобнее.
                    Сам же TASM до сих пор не превзойден в фичах, облегчающих жизнь при создании больших программ. Будь то удобные объявления прототипов функций (с небольшим контролем параметров!), или же поддержка ООП, позволяющая довольно удобно работать с технологией COM, а так же с DirectX (насквозь объектный зараза). Но, любителям все это ни к чему, они предпочитают примитив, чтобы выучить побыстрее :)
                    Цитата Jin X @
                    А где system.h?
                    В пакете, где же еще. Но, пакет большой и с разбегу разобраться в нем не получится. Аттачить?
                      Цитата Eretic @
                      Самый натуральный TASM
                      Значит, видимо, где-то, как минимум, $COLN и _ объявлены ранее...

                      Цитата Eretic @
                      Аттачить?
                      Пусть будет :yes:

                      Добавлено
                      Цитата Eretic @
                      Прикреплённый файлFORT.zip
                      Что-то какая-то уж очень большая программа (размер) для такого функционала...
                        Цитата Jin X @
                        Пусть будет

                        Чуть позже выложу. Нашлись еще кое-какие либы и какое-то описание по созданию на макросах команд IF/FOR и тд.
                        Цитата Jin X @
                        Что-то какая-то уж очень большая программа (размер) для такого функционала...

                        Это размер ядра Форт, со всеми стандартными словами и поддержкой двойных слов. Типа RTL у языков ЯВУ. Сама функция Dump занимает 160 байт. А если написать нормально:
                        ExpandedWrap disabled
                          $COLN MOD/4
                          _     I 4 MOD 0= IF SPACE ENDIF EXIT
                           
                          $COLN CI@
                          _     DUP I + C@ EXIT
                           
                          $COLN DUMP    ; ( a nlines -- ) вывод содержимого ряда адресов памяти
                          _     CR BASE @ >R                    ; сохраняем текущую базу счисления
                          _     HEX                             ; и устанавливаем шестнадцатеричную
                          _     0 FOR
                          _       #CA DUP U>D <# # # # # #> TYPE ':' EMIT
                          _       #HEX 16 0 FOR
                          _         MOD/4   ; группируем по 4 байта
                          _         CI@ U>D
                          _         <# # # #> TYPE SPACE
                          _       NEXT
                          _       #CHAR 16 0 FOR
                          _         MOD/4   ; группируем по 4 символа
                          _         CI@ DUP
                          _         BL 240 WITHIN NOT           ; печатный символ ASCII?
                          _         IF DROP 46 ENDIF EMIT
                          _       NEXT
                          _       16 + CR
                          _     NEXT
                          _     DROP
                          _     R> BASE !                       ; восстанавливаем базу счисления
                          _     EXIT
                        То сократили до 140 байт. Если же отказаться от форматного вывода, можем съэкономить еще десяток байт. Отказ от разбивки на столбцы по 4 байта - еще съэкономленных 20 байт. Отказ от цвета - еще десяток. В итоге вывод дампа можно свести к 100 байтам.
                          Только сейчас заметил, что макс. размер аттачей всего 100 кб. Маловато будет.
                            Даже в зипе?
                            Можно разбить на тома...
                            0 пользователей читают эту тему (0 гостей и 0 скрытых пользователей)
                            0 пользователей:


                            Рейтинг@Mail.ru
                            [ Script execution time: 0,0631 ]   [ 17 queries used ]   [ Generated: 29.03.24, 15:23 GMT ]