Поиск:

Ответ в темуСоздание новой темы Создание опроса
> передача параметров через стек, выводит мусор 
V
    Опции темы
Logree
Дата 5.12.2008, 19:55 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 331
Регистрация: 22.11.2006
Где: Самара

Репутация: 1
Всего: 2



простая програмка
Код

DSEG SEGMENT
mess 'Im procedure!$'
DSEG ENDS

SSEG SEGMENT STACK
db 0FFh DUP(?)
SSEG ENDS

CSEG SEGMENT
beg:

lea ax,mess
push ax 

call myproc

pop ax
mov ah,4ch
int 21h

myproc proc
push bp             
mov bp,sp             ; разве bp и sp оба не указывают на вершину стека? (пример из книги)

mov dx,[bp+4]      ; ну я так понимаю 2 - это  адрес возврата + 2 - bp , но 
                             ; ведь ещё есть само значение ax, только если написать +6 - программа виснет
                             ; а так выводит какой то мусор и строку
mov ah,09h
int 21h

mov sp,bp
pop bp
ret
myproc endp

CSEG ENDS
end beg


вопросы в коде.


--------------------
Самый распространенный способ дебага пятиста строк ассемблерного кода - очень долгий, очень пристальный и очень задумчивый взгляд.
PM MAIL ICQ   Вверх
Akina
Дата 5.12.2008, 20:14 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Советчик
****


Профиль
Группа: Модератор
Сообщений: 20581
Регистрация: 8.4.2004
Где: Зеленоград

Репутация: нет
Всего: 454



а DS у тебя чему равно, как полагаешь?


--------------------
 О(б)суждение моих действий - в соответствующей теме, пожалуйста. Или в РМ. И высшая инстанция - Администрация форума.

PM MAIL WWW ICQ Jabber   Вверх
Logree
Дата 5.12.2008, 20:35 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 331
Регистрация: 22.11.2006
Где: Самара

Репутация: 1
Всего: 2



это здесь набирал ассум забыл а впроге она есть дс на дсег указывает


--------------------
Самый распространенный способ дебага пятиста строк ассемблерного кода - очень долгий, очень пристальный и очень задумчивый взгляд.
PM MAIL ICQ   Вверх
Akina
Дата 5.12.2008, 20:55 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Советчик
****


Профиль
Группа: Модератор
Сообщений: 20581
Регистрация: 8.4.2004
Где: Зеленоград

Репутация: нет
Всего: 454



Logree, идите учить основы языка. ASSUME ничего не присваивает. А DS у вас указывает на PSP.


--------------------
 О(б)суждение моих действий - в соответствующей теме, пожалуйста. Или в РМ. И высшая инстанция - Администрация форума.

PM MAIL WWW ICQ Jabber   Вверх
Logree
Дата 5.12.2008, 21:39 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 331
Регистрация: 22.11.2006
Где: Самара

Репутация: 1
Всего: 2



нУ Ё МАЁ ЗАБЫЛ ж) 

и всётаки, так всё работает, но почему +4 а не +6
Код

push bp             
mov bp,sp             ; разве bp и sp оба не указывают на вершину стека? (пример из книги)

mov dx,[bp+4]      ; ну я так понимаю +2 - bp, +4 - это  адрес возврата, но 
                             ; ведь ещё есть само значение ax?


Это сообщение отредактировал(а) Logree - 6.12.2008, 05:34


--------------------
Самый распространенный способ дебага пятиста строк ассемблерного кода - очень долгий, очень пристальный и очень задумчивый взгляд.
PM MAIL ICQ   Вверх
Mikl_
Дата 8.12.2008, 05:16 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 537
Регистрация: 9.11.2007

Репутация: 6
Всего: 14



Logree, во-первых вместо lea ax,mess /push ax  можно сразу писать push offset mess
во вторых, привыкай писать так, чтобы процедуры сами выравнивали за собой стек после получения параметра то есть вместо 
Код
push параметр 
call myproc 
pop reg ; здесь вы не сколько восстанавливаете содержимое ax сколько выравниваете стековый указатель 
;sp после выхода из процедуры, обычно значение в регистре ax используют для передачи 
;результата работы процедуры
...
myproc proc 
... 
ret
myproc endp
 нужно писать вот так 
Код
push параметр1
 push параметр2
...
push параметрN
call myproc; процедура сама уберет из стека "мусор" в виде параметров
; <-- вот здесь нет никаких pop-ов
...
myproc proc 
... 
ret 2*N; N=количество параметров переданных через стек)
myproc endp


Это сообщение отредактировал(а) Mikl_ - 8.12.2008, 05:18
PM MAIL   Вверх
Mikl_
Дата 8.12.2008, 06:29 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 537
Регистрация: 9.11.2007

Репутация: 6
Всего: 14



Logree, Перед обращением к процедуре основная программа записала параметры в стек. Параметры записываются в стек слева направо: сначала первый параметр, затем второй и т.д. Команды основной программы, реализующие обращение к процедуре и состояние стека после входа в процедуру: 
Код
                                        ; Адрес  | содержимое
push 1                              ;SP→  |Адрес возврата
push 2                              ;SP+ 2 |4
push 3                              ;SP+ 4 |3
push 4                              ;SP+ 6 |2
call AddReg                    ;SP+  8 |1
Возникают вопросы: Как процедуре добраться до параметров? Как добраться к элементам стека без считывания из стека? Используем косвенную адресацию через регистр SP.
Код
AddReg proc 
mov dx,[sp+2];извлекаем параметры подпрограммы
mov cx,[sp+4]
mov bx,[sp+6]
mov ax,[sp+8]
...
ret
AddReg ENDP 

Но это был всего лишь частный случай, а если нам придет в голову использовать внутри процедуры команды PUSH и POP? Воспользуемся регистром BP, засылаем в него адрес вершины стека (содержимое регистра SP), а затем используем выражение вида [BP+i] для доступа к параметрам процедуры. Мы можем испортить содержимое регистра BP, а он может использоваться в основной программе. Поэтому сначала сохраним значение этого регистра в стеке, а затем пересылаем в регистр BP значение регистра SP. Входные и выходные действия процедуры
Код
                                                          ; Адрес         |Содержимое
AddReg PROC                               ;SP,BP →    |BPстарое 
PUSH BP                                        ;BP+ 2            | Адрес возврата
MOV BP,SP                                      ;BP+ 4           | 4                           
... ; команды процедуры AddReg ;BP+6         |3
POP BP                                             ; BP+8          |2
RET                                                    ; BP+10        |1
После записи в стек старого значения BP (BPстарое) для доступа к параметрам процедуры надо использовать следующие выражения: [BP+4] — для доступа к последнему параметру, [BP+6] — для доступа к предпоследнему параметру и так далее. Например, считывание последнего параметра в регистр DX осуществляется командой MOV DX,[BP+4]. После того как процедура отработает, стек должен быть в том же состоянии, в каком он был до использования процедуры. Восстанавливаем командой POP BP старое значение BP и после этого возможны два варианта завершения процедуры:
Первый вариант.После выполнения команды RET в стеке остаются использованные процедурой параметры и основная программа должна очистить стек. Но было бы лучше, если очистку стека будет делать сама процедура, так как обращений к процедуре может быть много и в основной программе команду ADD SP,2*k придется повторять многократно. Существует правило: если что-то может сделать и основная программа и процедура, то лучше, если это будет делать процедура.
Код
push 1 ;первая локальная переменная 
push 2 ;вторая локальная переменная 
push 3 ;третья локальная переменная 
push 4 ;четвертая локальная переменная 
call AddReg;команды процедуры 
ADD SP,2*4;принудительная очистка стека от 4 параметров слов

Второй вариант.Процедура сама очищает стек от параметров и передает управление по адресу возврата 
Код
...;команды процедуры 
POP BP ;восстановить старое значение BP 
RET 2*k ;принудительная очистка стека от k параметров слов 
AddReg ENDP; возврат из процедуры

По команде RET смещение из стека удаляется адрес возврата, затем стек очищается на указанное операндом число байтов и для перехода по адресу возврата выполняются следующие действия:
1) Значение из стека в IP
2) [значение из стека в CS]
3) SP=SP+смещение
(действие по восстановлению значения CS из стека выполняется лишь при дальнем возврате).
Команда RET — это на самом деле команда RET 0, то есть возврат без очистки стека. Операнд команды RET указывает на сколько байтов, а не слов надо очищать стек. Для очистки стека от k параметров, каждый из которых имел размер слова, был указан операнд 2*k. В операнде не должен учитываться адрес возврата — команда RET считывает его до очистки стека.

Это сообщение отредактировал(а) Mikl_ - 8.12.2008, 06:56
PM MAIL   Вверх
Logree
Дата 8.12.2008, 17:38 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 331
Регистрация: 22.11.2006
Где: Самара

Репутация: 1
Всего: 2



спасибоЖ) 


--------------------
Самый распространенный способ дебага пятиста строк ассемблерного кода - очень долгий, очень пристальный и очень задумчивый взгляд.
PM MAIL ICQ   Вверх
Logree
Дата 21.12.2008, 21:02 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 331
Регистрация: 22.11.2006
Где: Самара

Репутация: 1
Всего: 2



поговорим ещё немного вот пример:

гдавная программа
Код

extrn read_str:far,print_str:far
DSEG SEGMENT

FILE_NAME db 'Enter a file name: '
W_OK db 'Complit!'
W_ERR db 'Error!'

DSEG ENDS

SSEG SEGMENT STACK
db 0FFh DUP(?)
SSEG ENDS

CSEG SEGMENT
ASSUME CS:CSEG,DS:DSEG,SS:SSEG
INCLUDE file.asm
INCLUDE prt_str.asm

begin:
  mov ax,DSEG
  mov ds,ax
  mov ax,SSEG
  mov ss,ax
  xor ax,ax

  push offset FILE_NAME
  call read_str
  push offset FILE_NAME
  call print_str

  mov ah,4Ch
  int 21h

CSEG ENDS
end begin



file.asm
Код


public read_str
READSTR SEGMENT
ASSUME CS:READSTR

; 1 parameter(s):
; offset filename

read_str proc far

;=========== save registers ========
  push ax 
  push bx
  push cx
  push dx
  push si
  push di
  push bp
  push sp
  mov  bp,sp  
;=========== proc begin ==========
  mov  si,0
  mov bx,[bp+20]
;=========== read and save key =========
key:
  mov  ah,10h
  int  16h 
;=========== if not symbol =========
  cmp  al,0
  je   key
;=========== if enter ==========
  cmp  al,0Dh
  je   ext
;=========== save simbol SI ========
  mov  [bx+si],al
  inc  si
;=========== print simbol =========
  mov  ah,0Eh
  int  10h
  jmp  key
;=========== exit ==========
ext:
  mov [bx+si+1],0h
  mov  sp,bp
  pop sp
  pop bp
  pop di
  pop si
  pop dx
  pop cx
  pop bx
  pop ax

  ret 2
read_str endp

READSTR ENDS
end



prt_str.asm
Код

public print_str:far
PRINTSTR SEGMENT
ASSUME CS:PRINTSTR

; 1 parametr(s)
; offset string

print_str proc far

;========== save registers ===========
  push  ax
  push  si
  push  bp
  mov   bp,sp
  mov   si,[bp+8]
  mov   ah,0Eh
;========== next symbol ===========
next_s:
  lodsb             ; mov mem2al inc si
  cmp   al,0h
  je    ext
  int   10h
  jmp   next_s

ext:
  mov   sp,bp
  pop   bp
  pop   si
  pop   ax
  ret   2
print_str endp
PRINTSTR ENDS
end


смысл прост вызывающая прграмма и две другие (название соответствует содержанию)
1. выдаёт множество ошибок как например незакрытый сегмент и что-то про mov [bx+si+1],0h  в file.asm покажите на все ошибки
2. если у меня far значит каждый параметр занесённый в стек будет 4 байта те 1. [bp+36] 2.[bp+16] да и загружать сначала придётся первае 2 байта а потом остальные ?


Это сообщение отредактировал(а) Logree - 21.12.2008, 21:07


--------------------
Самый распространенный способ дебага пятиста строк ассемблерного кода - очень долгий, очень пристальный и очень задумчивый взгляд.
PM MAIL ICQ   Вверх
Mikl_
Дата 22.12.2008, 04:43 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 537
Регистрация: 9.11.2007

Репутация: 6
Всего: 14



Logree
1) если объявляешь процедуру как far, тогда заканчиваться она должна обязательно на retf и вызов ее должен быть call far 
2) вместо push ax/ ... /push bp можно написать pusha соответственно вместо pop bp/ ... /pop ax есть команда popa
3) если пытаешься получить аргумент из стека то обращатья к нему лучше через bp -- mov ax,[bp] подразумевается mov ax,ss:[bp] если аргумент в стеке а адресация через bx, si, di тогда префикс указывается явно mov ax,ss:[bx+si]
4) все свои действия контролируй через отладчик -- мало ли кто чего тебе насоветует -- в отладчике все ошибки видно
PM MAIL   Вверх
Logree
Дата 22.12.2008, 23:32 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 331
Регистрация: 22.11.2006
Где: Самара

Репутация: 1
Всего: 2



Цитата

1) если объявляешь процедуру как far, тогда заканчиваться она должна обязательно на retf и вызов ее должен быть call far 

это для всех процов?

Цитата

2) вместо push ax/ ... /push bp можно написать pusha соответственно вместо pop bp/ ... /pop ax есть команда popa

так сначала и было сделано но потм оказалось что придётся добавлять .386 мне было влом(ну просто не хотелось) тем более я только учусь.. лучше видить что и как

Цитата

3) если пытаешься получить аргумент из стека то обращатья к нему лучше через bp -- mov ax,[bp] подразумевается mov ax,ss:[bp] если аргумент в стеке а адресация через bx, si, di тогда префикс указывается явно mov ax,ss:[bx+si]


не понял к чему это...

и где ошибки? т е в чём причина? 
Код

Turbo Assembler  Version 4.1  Copyright (c) 1988, 1996 Borland International

Assembling file:   flp_write.ASM
public read_str:far
**Error** file.asm(2) Can't make variable public: READ_STR
read_str proc far
**Error** file.asm(9) Symbol already different kind: READ_STR
  mov [bx+si+1],0h
*Warning* file.asm(43) Argument needs type override
end
*Warning* file.asm(58) Open segment: CSEG
Error messages:    2
Warning messages:  2
Passes:            1
Remaining memory:  407k





--------------------
Самый распространенный способ дебага пятиста строк ассемблерного кода - очень долгий, очень пристальный и очень задумчивый взгляд.
PM MAIL ICQ   Вверх
Mikl_
Дата 23.12.2008, 05:00 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 537
Регистрация: 9.11.2007

Репутация: 6
Всего: 14



Logree
1) справедливо и для AMD, и для Intel, потому что у этих команд разная кодировка: 
retn = 0C3h 
retn число = 0C2 число 
retf = 0CBh
retf число = 0CA  число 
call near = 0E8XXXX 
call far = 0FFXXXX или 9AXXXX зависит от контекста
2) для поддержки pusha и popa достаточно в заголовке поставить .286
если поставить .386 тогда pusha размещает в стеке содержимое регистров  в следующей последовательности: EAX, ECX, EDX, EBX, ESP, EBP, ESI, EDI. а push eax это не одно и тоже что push ax. Для их различия иногда пишут PUSHAD и PUSHAW
3) если написано невнятно -- найди аналогичное место в учебнике и перечитай
4) С синтаксическими ошибками разбирайся сам -- больше будет пользы!
PM MAIL   Вверх
Logree
Дата 24.12.2008, 01:41 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 331
Регистрация: 22.11.2006
Где: Самара

Репутация: 1
Всего: 2



А разве tasm один раз по программе проходит?

со всеми ошибками разобрался методом логических размышлений...

Цитата

1) если объявляешь процедуру как far, тогда заканчиваться она должна обязательно на retf

он же автоматически ret на retf заменяет


теперь всё нормально одна проблемма:
Код

  mov [bx+si+1],0h
*Warning* file.asm(43) Argument needs type override

почему так  mov  [bx+si],al ему нравиться а так нет?

пробывал mov ss:[bx+si+1],0h что-то не помогло в чём дело?

при линковке пишет
Код

Fatal: No program entry point


я так понимаю нет точки входа в программу... и возможно из-за того что я написа вот так
Код

INCLUDE file.asm
INCLUDE prt_str.asm

DSEG SEGMENT

FILE_NAME db 'Enter a file name: '
W_OK db 'Complit!'
W_ERR db 'Error!'

DSEG ENDS

SSEG SEGMENT STACK
db 0FFh DUP(?)
SSEG ENDS

CSEG SEGMENT
ASSUME CS:CSEG,DS:DSEG,SS:SSEG


или я что со стеко намудрил?

ps я правда рад бы посмотреть её под отладчиком да  где б экзэшник взять smile 

Это сообщение отредактировал(а) Logree - 24.12.2008, 01:43


--------------------
Самый распространенный способ дебага пятиста строк ассемблерного кода - очень долгий, очень пристальный и очень задумчивый взгляд.
PM MAIL ICQ   Вверх
Mikl_
Дата 24.12.2008, 05:25 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 537
Регистрация: 9.11.2007

Репутация: 6
Всего: 14



Logree
1) mov [bx+si+1],0h
*Warning* file.asm(43) Argument needs type override
Ну во-первых, Warning это предупреждение о возможной ошибке, а не об ошибке -- Error
Смысл предупреждения -- неоднозначное трактование записи команды mov [bx+si+1],0h может быть mov byte ptr [bx+si+1],0h а может быть mov word ptr [bx+si+1],0h -- кодировки у этих команд разные -- компилятор подставил, то что считал нужным, но на всякий случай предупредил тебя -- вдруг он это сделал неправильно -- когда ты пишешь mov  [bx+si],al  однозначно видно, что ты передаешь байт, если написано mov [bx+si+1],1000h по величине числа тоже видно, что передается слово, а вот с числами в диаппазоне от -128 до +127 возникнет неоднозначность, что имеет ввиду программист слово или байт? Избежать это помогает определение типа аргумента -- argument type override -- диррективы word ptr и byte ptr
2) Fatal: No program entry point
вместо первой метки begin: и end begin напиши start: и end start -- возможно из-за этого. И строка 
ASSUME CS:CSEG,DS:DSEG,SS:SSEG можно и без неё обойтись -- пишешь .code вместо CSEG SEGMENT ... CSEG ENDS, .data вместо DSEG SEGMENT ... DSEG ENDS, .stack вместо SSEG SEGMENT ... SSEG ENDS как вас учат -- это какая-то архаичная форма записи, по крайней мере уже 20 лет назад так не писали...
Лучше возьми исходный текст работающей программы и постепенно видоизменяй его под свой исходник -- внес небольшие изменения -- компилируешь, не компилируется -- разбираешься почему, компилируется -- вносишь изменения дальше
3) я правда рад бы посмотреть её под отладчиком да  где б экзэшник взять 
Пока не избавишься от синтаксических ошибок экзешник не получится -- отладчик это следующий этап после компиляции
PM MAIL   Вверх
Logree
Дата 24.12.2008, 17:55 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 331
Регистрация: 22.11.2006
Где: Самара

Репутация: 1
Всего: 2



Цитата

1) mov [bx+si+1],0h
*Warning* file.asm(43) Argument needs type override
Ну во-первых, Warning это предупреждение о возможной ошибке, а не об ошибке -- Error
Смысл предупреждения -- неоднозначное трактование записи команды mov [bx+si+1],0h может быть mov byte ptr [bx+si+1],0h а может быть mov word ptr [bx+si+1],0h -- кодировки у этих команд разные -- компилятор подставил, то что считал нужным, но на всякий случай предупредил тебя -- вдруг он это сделал неправильно -- когда ты пишешь mov  [bx+si],al  однозначно видно, что ты передаешь байт, если написано mov [bx+si+1],1000h по величине числа тоже видно, что передается слово, а вот с числами в диаппазоне от -128 до +127 возникнет неоднозначность, что имеет ввиду программист слово или байт? Избежать это помогает определение типа аргумента -- argument type override -- диррективы word ptr и byte ptr


я рассматривал этот вариант но проверить руки не дошли... smile

Цитата

2) Fatal: No program entry point
вместо первой метки begin: и end begin напиши start: и end start -- возможно из-за этого. И строка 
ASSUME CS:CSEG,DS:DSEG,SS:SSEG можно и без неё обойтись -- пишешь .code вместо CSEG SEGMENT ... CSEG ENDS, .data вместо DSEG SEGMENT ... DSEG ENDS, .stack вместо SSEG SEGMENT ... SSEG ENDS как вас учат -- это какая-то архаичная форма записи, по крайней мере уже 20 лет назад так не писали...
Лучше возьми исходный текст работающей программы и постепенно видоизменяй его под свой исходник -- внес небольшие изменения -- компилируешь, не компилируется -- разбираешься почему, компилируется -- вносишь изменения дальше

ему пофиг что я та м пишу start, entry, begin, не видит он точки входа в чём ещё может быт дело?
ПОЧЕМУ-ТО МЕНЯ ВОРОТИТ ОТ ВСЕХ ЭТИХ .code .STACK И Т Д
буду под винду писать буду юзать  .code а пока лучше постаринке...


Цитата

я правда рад бы посмотреть её под отладчиком да  где б экзэшник взять 

я в курсе это как бы шутка была... ха ха smile
 

Это сообщение отредактировал(а) Logree - 24.12.2008, 18:05


--------------------
Самый распространенный способ дебага пятиста строк ассемблерного кода - очень долгий, очень пристальный и очень задумчивый взгляд.
PM MAIL ICQ   Вверх
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Asm: Общие вопросы"
MAKCim
  • Проставьте несколько ключевых слов темы, чтобы её можно было легче найти.
  • Не забывайте пользоваться кнопкой КОД.
  • Телепатов на форуме нет! Задавайте чёткий, конкретный и полный вопрос. Указывайте полностью ошибки компилятора и компоновщика.
  • Новое сообщение должно иметь прямое отношение к разделу форума. Флуд, флейм, оффтопик запрещены.
  • Категорически запрещается обсуждение вареза, "кряков", взлома программ и т.д.

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, MAKCim.

 
 
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Asm: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.0980 ]   [ Использовано запросов: 21 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.