реклама на сайте
подробности

 
 
2 страниц V   1 2 >  
Reply to this topicStart new topic
> Прошивки AT89S8252, как получить общий исполняемый файл прошивки?
Kofey Nik
сообщение Apr 6 2011, 09:01
Сообщение #1


Участник
*

Группа: Участник
Сообщений: 41
Регистрация: 5-07-05
Из: Нижний Новгород
Пользователь №: 6 540



У AT89S8252 имеется прошивка внутренней флэш программ (8к) плюс внешняя ПЗУ (64к). Как получить целиковый файл исполняемой программы? По-идее, поскольку в таких случаях вначале исполняется внутренняя прошивка а потом вшнешняя, то надо наложить эти 8к на начало ПЗУ, но тогда исчезнут масса служебных строк, необходимых программе. А если состыковать файл ПЗУ в конец файла внутренней флэш, тогда размер прошивки превысит 64К - как процессору с 16-разрядной шиной адреса добраться до конца такой программы?


--------------------
Все мы учились понемногу - чему нибудь и как нибудь :).
Go to the top of the page
 
+Quote Post
Палыч
сообщение Apr 6 2011, 10:00
Сообщение #2


Гуру
******

Группа: Свой
Сообщений: 2 399
Регистрация: 10-05-06
Из: г. Новочеркасск
Пользователь №: 16 954



Цитата(Kofey Nik @ Apr 6 2011, 13:01) *
Как получить целиковый файл исполняемой программы?
Что значит "целиковый"? C какой целью Вы хотите получить такой файл?

Цитата(Kofey Nik @ Apr 6 2011, 13:01) *
По-идее, поскольку в таких случаях вначале исполняется внутренняя прошивка а потом вшнешняя...
Не обязательно в такой последовательности. При обращении по адресу бОльшем, чем максимальный адрес внутренней памяти программ, обращение производится к внешней памяти.

Цитата(Kofey Nik @ Apr 6 2011, 13:01) *
А если состыковать файл ПЗУ в конец файла внутренней флэш, тогда размер прошивки превысит 64К - как процессору с 16-разрядной шиной адреса добраться до конца такой программы?
Вполне возможно, что младшие 8К внешней памяти вовсе не используются... Тут уж - как построено ПО нужно смотреть...

Если - не секрет: что это за устройство такое?
Go to the top of the page
 
+Quote Post
Kofey Nik
сообщение Apr 6 2011, 12:57
Сообщение #3


Участник
*

Группа: Участник
Сообщений: 41
Регистрация: 5-07-05
Из: Нижний Новгород
Пользователь №: 6 540



Цитата(Палыч @ Apr 6 2011, 14:00) *
Что значит "целиковый"? C какой целью Вы хотите получить такой файл?

Попробовать дизассемблировать - нужно исправить одно ограничение в прошивке. Опыт с 51-м был. Целостная прошивка - ну, в аппаратном виде носителей программы два, а мне нужно получить один непрерывный файл с непрерывным адресным пространством.

Цитата(Палыч @ Apr 6 2011, 14:00) *
Не обязательно в такой последовательности. При обращении по адресу бОльшем, чем максимальный адрес внутренней памяти программ, обращение производится к внешней памяти.

Начиная с какого адреса во внешнем ПЗУ? Максимальный_адрес +1 ? Это я и имел в виду.

Цитата(Палыч @ Apr 6 2011, 14:00) *
Вполне возможно, что младшие 8К внешней памяти вовсе не используются... Тут уж - как построено ПО нужно смотреть...

Первый байт равен 02 только во внутренней флэш, ПЗУ начинается с 20, следующий тоже 20 - это символы кодовой страницы ASCII - они нужны для работы программы, затенять их внутренней прошивкой чревато их исключением. Вот в чем проблема для меня.

если наложить внутреннее содержимое (из флэш) на первые 8К пространства внешнего ПЗУ программ, то при дизасе получается галиматья -

...
code:1FFA mov R6, #8
code:1FFC mov R1, #0x68 ; 'h' ; - после этой команды нет перехода на исполняемый код !!!
code:1FFC ; END OF FUNCTION CHUNK FOR start
code:1FFC ; ---------------------------------------------------------------------------
code:1FFE .byte 0x12
code:1FFF .byte 0x61 ; a
code:1FFF ; end of 'code'
code:1FFF
seg_01:00002000 ; ===========================================================================
seg_01:00002000
seg_01:00002000 ; Segment type: Pure code
seg_01:00002000 ;.segment seg_01
seg_01:00002000 ; .equ $, 0x2000
seg_01:00002000 ; START OF FUNCTION CHUNK FOR seg_01_4FC8
seg_01:00002000 seg_01_2000: .byte 0xFF
...


Сообщение отредактировал Kofey Nik - Apr 6 2011, 12:49


--------------------
Все мы учились понемногу - чему нибудь и как нибудь :).
Go to the top of the page
 
+Quote Post
AHTOXA
сообщение Apr 6 2011, 17:16
Сообщение #4


фанат дивана
******

Группа: Свой
Сообщений: 3 387
Регистрация: 9-08-07
Из: Уфа
Пользователь №: 29 684



А на ноге EA что, земля или питание? Если земля, то внутренняя память программ не используется.


--------------------
Если бы я знал, что такое электричество...
Go to the top of the page
 
+Quote Post
Палыч
сообщение Apr 6 2011, 19:18
Сообщение #5


Гуру
******

Группа: Свой
Сообщений: 2 399
Регистрация: 10-05-06
Из: г. Новочеркасск
Пользователь №: 16 954



Цитата(Kofey Nik @ Apr 6 2011, 16:57) *
Попробовать дизассемблировать - нужно исправить одно ограничение в прошивке. Опыт с 51-м был. Целостная прошивка - ну, в аппаратном виде носителей программы два, а мне нужно получить один непрерывный файл с непрерывным адресным пространством.
Э-э-э-э... Чего это вдруг - "с непрерывным адресным пространством"? В МК51 "адресных пространств" аж целых три штуки, и из них никак не получить одно непрерывное. При дизассемблировании нужно использовать два из них: дизасеммблибуются внутренняя flash и внешнее ПЗУ - каждое отдельно от другого, но с использованием результатов дизассемблирования другого...

Цитата(Kofey Nik @ Apr 6 2011, 16:57) *
если наложить внутреннее содержимое (из флэш) на первые 8К пространства внешнего ПЗУ программ, то при дизасе получается галиматья
Вовсе не обязательно, что выполнение программы плавно "перетечет" из внутренней flash во нешнее ПЗУ. Например, может быть, что во внешнем ПЗУ находится не исполняемый код, а некоторые данные (например, изображение, выводимое на некий экран), или набор процедур/подпрограмм, вызываемый из "основной" программы (программы, расположенной во внутренней flash).

Если подвести итог под вышесказанным: 1) необходимо дизассемблировать вначале прошивку внутренней flash, при этом обратить внимание на использование обращений к нешнему ПЗУ; 2) с учетом анализа дизассемблированного кода из п.1 произвести дизассемблирование прошивки внешнего ПЗУ.

Конечно, всё это с учетом замечания АНТОХИ
Go to the top of the page
 
+Quote Post
Kofey Nik
сообщение Apr 7 2011, 05:14
Сообщение #6


Участник
*

Группа: Участник
Сообщений: 41
Регистрация: 5-07-05
Из: Нижний Новгород
Пользователь №: 6 540



AHTOXA
Конечно же, ЕА=1. Не случайно же первый байт во флэш - команда стандарного для этих процессоров безусловного дальнего перехода ljmp (02h).

Цитата(Палыч @ Apr 6 2011, 23:18) *
Э-э-э-э... Чего это вдруг - "с непрерывным адресным пространством"? В МК51 "адресных пространств" аж целых три штуки, и из них никак не получить одно непрерывное. При дизассемблировании нужно использовать два из них: дизасеммблибуются внутренняя flash и внешнее ПЗУ - каждое отдельно от другого, но с использованием результатов дизассемблирования другого...

Палыч, ну это же прописные истины, мне они ведомы. sm.gif Я только не понял, как можно использовать результаты дизассемблирования одной прошивки для другой.
Для ядра микроконтроллера программа вместе с данными (получаемыми с помощью команды MOVC) представляет одно адресное пространство (если только не используется переключение между банками с помощью управляющих линий, но это совсем уж сложный случай, за такие я бы не взялся - там надо иметь поистине шахматическую память). В программе используются дальние переходы, которые могут быть физически быть из внутренней флэш во внутреннюю и наоборот. Вот его-то мне и надо получить, чтобы понять логику программы, чтобы исправить в нужных местах код.

Цитата(Палыч @ Apr 6 2011, 23:18) *
Вовсе не обязательно, что выполнение программы плавно "перетечет" из внутренней flash во нешнее ПЗУ. Например, может быть, что во внешнем ПЗУ находится не исполняемый код, а некоторые данные (например, изображение, выводимое на некий экран), или набор процедур/подпрограмм, вызываемый из "основной" программы (программы, расположенной во внутренней flash).

Ну смотрите - если после команды

mov R1, #0x68

идет не следующая команда, а массив данных, этот код обрывается для процессора, и тогда он воспринимает данные за команды (например, байты 20 хх хх примет за код "JB имя_регистра адрес_ближнего_перехода"), в результате процессор просто стопорится или ресетится, дойдя до ситуации исключения.

Вот почему я был удивлен таким построением суммарной прошивки.

Цитата(Палыч @ Apr 6 2011, 23:18) *
Если подвести итог под вышесказанным: 1) необходимо дизассемблировать вначале прошивку внутренней flash, при этом обратить внимание на использование обращений к нешнему ПЗУ; 2) с учетом анализа дизассемблированного кода из п.1 произвести дизассемблирование прошивки внешнего ПЗУ.
Обращения к данным можно просто отследить - для этого используется команда MOVX, если это не память программ, а в нашем случае это именно память программ (обращение в цикле получения команды по сигналу *PSEN). В том-то и дело, что во внешнем ПЗУ находится основной массив исполняемой программы устройства.

Сообщение отредактировал Kofey Nik - Apr 7 2011, 05:25


--------------------
Все мы учились понемногу - чему нибудь и как нибудь :).
Go to the top of the page
 
+Quote Post
Палыч
сообщение Apr 7 2011, 06:17
Сообщение #7


Гуру
******

Группа: Свой
Сообщений: 2 399
Регистрация: 10-05-06
Из: г. Новочеркасск
Пользователь №: 16 954



Цитата(Kofey Nik @ Apr 7 2011, 09:14) *
Я только не понял, как можно использовать результаты дизассемблирования одной прошивки для другой.
На Вашем месте я бы получил хороший (в первом приближении) результат дизассемблирования прошивки внутренней flash (уж не знаю, что Вы для этого используете - рекомендую IDA - можно уточнять процесс дизассемблирования по мере понимания организации вычислительного процесса и размещения/назначения данных). По результату дизассемблирования внутренней flash определить исходные данные для дизассемблирования внешнего ПЗУ: адреса подпрограмм, данных, сруктура данных и т.п., и уже потом дизассемблировать внешнюю прошивку. Анализ внешней прошивки, возможно, уточнит что-то для понимания внутренней, и так - по кругу до полного понимания...

Цитата(Kofey Nik @ Apr 7 2011, 09:14) *
Ну смотрите - если после команды ... идет не следующая команда, а массив данных...
Вы должны понимать, что дизассемблеры, если что-то делают в автоматическом режиме, то не всегда верно! Вполне возможно, что команда, которую Вы привели в качестве примера, и не команда вовсе, а часть неких данных/констант - используемый Вами дизассемблер мог банально не разобраться с видом информации...

Цитата(Kofey Nik @ Apr 7 2011, 09:14) *
Обращения к данным можно просто отследить - для этого используется команда MOVX, если это не память программ, а в нашем случае это именно память программ (обращение в цикле получения команды по сигналу *PSEN). В том-то и дело, что во внешнем ПЗУ находится основной массив исполняемой программы устройства.
Данные из внешней памяти можно получить и командой movc biggrin.gif
Последнее же Ваше заявление о программе во внешнем ПЗУ - голословно, поскольку Вы не имеете сколько нибудь приемлемого результата дизассемблирования внутренней flash. Или на сигнал PSEN смотрели, и там строго в каждом цикле обращение?
Go to the top of the page
 
+Quote Post
Kofey Nik
сообщение Apr 7 2011, 07:13
Сообщение #8


Участник
*

Группа: Участник
Сообщений: 41
Регистрация: 5-07-05
Из: Нижний Новгород
Пользователь №: 6 540



Цитата(Палыч @ Apr 7 2011, 10:17) *
На Вашем месте я бы получил хороший (в первом приближении) результат дизассемблирования прошивки внутренней flash (уж не знаю, что Вы для этого используете - рекомендую IDA - можно уточнять процесс дизассемблирования по мере понимания организации вычислительного процесса и размещения/назначения данных). По результату дизассемблирования внутренней flash определить исходные данные для дизассемблирования внешнего ПЗУ: адреса подпрограмм, данных, сруктура данных и т.п., и уже потом дизассемблировать внешнюю прошивку. Анализ внешней прошивки, возможно, уточнит что-то для понимания внутренней, и так - по кругу до полного понимания...

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

Цитата(Палыч @ Apr 7 2011, 10:17) *
Вы должны понимать, что дизассемблеры, если что-то делают в автоматическом режиме, то не всегда верно! Вполне возможно, что команда, которую Вы привели в качестве примера, и не команда вовсе, а часть неких данных/констант - используемый Вами дизассемблер мог банально не разобраться с видом информации...

Нет, код совершенно логически корректный, в нем используется в том числе команда lcall code_12E0, подпрограмма которой корректна, завершается командой ret, и на нее имеются ссылки из других фрагментов программы флэш с аналогичными инициализирующими параметрами. Это точно не данные, это код.
Кроме того, в последнем фрагменте кода флэш идет вызов подпрограмм по адресам 61AE и 61FF, которые физически располагаются во другом носителе программного кода (внешнем ПЗУ).

Цитата(Палыч @ Apr 7 2011, 10:17) *
Последнее же Ваше заявление о программе во внешнем ПЗУ - голословно, поскольку Вы не имеете сколько нибудь приемлемого результата дизассемблирования внутренней flash. Или на сигнал PSEN смотрели, и там строго в каждом цикле обращение?

Слушайте, давайте не будем делать из меня наивного человека, который только вчера занялся цифровой схемотехникой. Системная плата вовсе не случайно имеет внешнее ПЗУ с подсоединением PSEN, кроме того аппарат просто не может работать в объеме программы 8 килобайт - это ему на один зуб не хватит. если уж так важны дополнительные доказательства, то уверяю Вас, выборка команд по формированию PSEN происходит регулярно.

Сообщение отредактировал Kofey Nik - Apr 7 2011, 07:14


--------------------
Все мы учились понемногу - чему нибудь и как нибудь :).
Go to the top of the page
 
+Quote Post
Палыч
сообщение Apr 7 2011, 07:46
Сообщение #9


Гуру
******

Группа: Свой
Сообщений: 2 399
Регистрация: 10-05-06
Из: г. Новочеркасск
Пользователь №: 16 954



Цитата(Kofey Nik @ Apr 7 2011, 11:13) *
Получить дизассемлированный код мне дело двух минут, и конечно же, я это давно уже сделал и отдельно для флэш, и отдельно для ПЗУ, и для обоих вариантов компоновки единого файла программы микроконтроллера.
По своему опыту знаю, что получить хороший дизассемблерный код, по которому можно что-то разумно судить - дело для такого объёма кода, как минимум, нескольких дней. Возможно, что Ваши проблемы как раз в тех "двух минутах" biggrin.gif
Go to the top of the page
 
+Quote Post
Kofey Nik
сообщение Apr 7 2011, 08:17
Сообщение #10


Участник
*

Группа: Участник
Сообщений: 41
Регистрация: 5-07-05
Из: Нижний Новгород
Пользователь №: 6 540



Цитата(Палыч @ Apr 7 2011, 11:46) *
По своему опыту знаю, что получить хороший дизассемблерный код, по которому можно что-то разумно судить - дело для такого объёма кода, как минимум, нескольких дней. Возможно, что Ваши проблемы как раз в тех "двух минутах" biggrin.gif
Возможно.
Но я предлагаю Вам самому посмотреть на этот фрагмент окончания прошивки во внутренней флэш:


code:00001FC7 mov DPTR, #0xBF93
code:00001FCA mov A, RAM_73
code:00001FCC dec A
code:00001FCD lcall code_1B4E; (см. ниже)
code:00001FD0 mov R6, #0xB
code:00001FD2 mov R1, #0x58 ; 'X'
code:00001FD4 lcall code_12E0 ; (см. ниже)
code:00001FD7 mov DPTR, #0xC128
code:00001FDA mov R4, RAM_59
code:00001FDC mov RAM_8, RAM_58
code:00001FDF mov B, #8 ; B-Register
code:00001FE2 lcall code_493B ; вызов кода за пределами 8К
code:00001FE5 mov R6, #0
code:00001FE7 lcall code_1CE5
code:00001FEA mov RAM_63, RAM_73
code:00001FED mov DPTR, #4
code:00001FF0 mov R1, #0x5A ; 'Z'
code:00001FF2 mov R6, #0xA
code:00001FF4 lcall code_61AE ; вызов кода за пределами 8К
code:00001FF7 mov DPTR, #0x39 ; '9'
code:00001FFA mov R6, #8
code:00001FFC mov R1, #0x68 ; 'h'
code:00001FFE lcall code_61FF ; вызов кода за пределами 8К


Из них подпрограмма, вызываемая из 1FCD (lcall code_1B4E) ---

code:00001B4E code_1B4E:
code:00001B4E mov B, #0x10 ; B-Register
code:00001B51 mul AB
code:00001B52 add A, DPL ; Data Pointer, Low Byte
code:00001B54 mov DPL, A ; Data Pointer, Low Byte
code:00001B56 mov A, B ; B-Register
code:00001B58 addc A, DPH ; Data Pointer, High Byte
code:00001B5A mov DPH, A ; Data Pointer, High Byte
code:00001B5C ret

- совершенно логичный код.

Далее - подпрограмма, вызываемая из 1FD4 (lcall code_12E0) ---

code:000012E0 code_12E0:
code:000012E0 clr C
code:000012E1 lcall code_12F2
code:000012E4 mov @R1, A
code:000012E5 ret

как видно, она вызывается из 1FD4, а также из 1F43, при этом вызов из 1F43 происходит с такими же, как и в случае вызова из 1FD4, инициализирующими параметрами:
mov R6, #значение
mov R1, #значение

Это точно код, нет никаких сомнений.



--------------------
Все мы учились понемногу - чему нибудь и как нибудь :).
Go to the top of the page
 
+Quote Post
Палыч
сообщение Apr 7 2011, 08:59
Сообщение #11


Гуру
******

Группа: Свой
Сообщений: 2 399
Регистрация: 10-05-06
Из: г. Новочеркасск
Пользователь №: 16 954



Цитата(Kofey Nik @ Apr 7 2011, 12:17) *
... предлагаю Вам самому посмотреть...
Посмотрел. Из увиденного можно предложить гипотезу (не факт, требует проверки), что код занимает весь объём внутреннего ПЗУ и внешнего ПЗУ с адресами от 2000 и, может быть, до конца. Первые 8к внешнего ПЗУ либо не используются, либо используются для хранения константных данных. Для дизассемблирования необходимо в считанной прошивке внешнего ПЗУ заменить первые 8к на данные из считанной прошивки внутреннего ПЗУ. Полученный файл подвергнуть дизассемблированию. Первые 8к внешнего ПЗУ выделить в отдельный файл для возможного последующего использования.
Если я Вас правильно понял, то Вам это было понятно изначально... Зачем тогда создали эту тему? В чем у Вас проблема?
Go to the top of the page
 
+Quote Post
Kofey Nik
сообщение Apr 7 2011, 09:33
Сообщение #12


Участник
*

Группа: Участник
Сообщений: 41
Регистрация: 5-07-05
Из: Нижний Новгород
Пользователь №: 6 540



Цитата(Палыч @ Apr 7 2011, 12:59) *
Посмотрел. Из увиденного можно предложить гипотезу (не факт, требует проверки), что код занимает весь объём внутреннего ПЗУ и внешнего ПЗУ с адресами от 2000 и, может быть, до конца. Первые 8к внешнего ПЗУ либо не используются, либо используются для хранения константных данных. Для дизассемблирования необходимо в считанной прошивке внешнего ПЗУ заменить первые 8к на данные из считанной прошивки внутреннего ПЗУ. Полученный файл подвергнуть дизассемблированию. Первые 8к внешнего ПЗУ выделить в отдельный файл для возможного последующего использования.
Если я Вас правильно понял, то Вам это было понятно изначально... Зачем тогда создали эту тему? В чем у Вас проблема?

Ваши заключения верные, по крайней мере из прошивки флэш вызывается корректная и логичная подпрограмма с адресом 61AE ---

seg_01:61AE seg_01_61AE:
seg_01:61AE ; seg_01_61AE+5j
seg_01:61AE mov A, @R1
seg_01:61AF lcall code_1AB0+1 ; - здесь проблема: при вызове попадаем на середину команды (т.е. операнд) - видимо, ошибка дизаса
seg_01:61B2 inc R1
seg_01:61B3 djnz R6, seg_01_61AE
seg_01:61B5 ret

А в чем проблема, я уже написал - пропадают все данные из первых 8К внешнего ПЗУ, этих данных больше нигде нет, а они нужны - это служебные слова, они используются при индикации работы аппарата. Вот я и решил уточнить у сведующих людей.

Кроме того, есть вопрос (в познавательских целях) код во флэш обрывается так:
12 (lcall) 61 (первый байт адреса вызываемой подпрограммы). Следующий байт (который должен служить младшим байтом адреса подпрограммы) уже находится во внешнем ПЗУ, а как мне представляется, выборка команд происходит целиком, за один цикл, так что здесь процессор не может получить полноценную команду.

Или нет проблем получить недостающий этой команде байт, который находится уже в другом носителе?



Но кажется, я начал понимать, в чем тут дело - кропме PSEN к выводу ОЕ приходит еще и сигнал RD !! Т.е. эти данные доступны по обычному циклу чтения внешней памяти (не программ). Т.е. как Вы и предположили - "используются для хранения константных данных".

Вроде, все ясно. Всем спасибо.


--------------------
Все мы учились понемногу - чему нибудь и как нибудь :).
Go to the top of the page
 
+Quote Post
Палыч
сообщение Apr 7 2011, 10:04
Сообщение #13


Гуру
******

Группа: Свой
Сообщений: 2 399
Регистрация: 10-05-06
Из: г. Новочеркасск
Пользователь №: 16 954



Цитата(Kofey Nik @ Apr 7 2011, 13:33) *
Кроме того, есть вопрос (в познавательских целях)...
Команды (впрочем, как и данные) из внешнего ПЗУ/ОЗУ считываются побайтно (в "классике" из внутреннего ПЗУ - то же). Так что проблем, вроде бы, быть не должно.
Go to the top of the page
 
+Quote Post
Harbinger
сообщение Apr 9 2011, 05:29
Сообщение #14


старший лаборант
******

Группа: Свой
Сообщений: 2 702
Регистрация: 30-09-05
Из: ЮЗЖД
Пользователь №: 9 097



Цитата(Kofey Nik @ Apr 7 2011, 12:33) *
"используются для хранения константных данных".

Тогда где-то должны найтись MOVX, ссылающиеся на те адреса.


--------------------
Китайская комплектация - европейское качество! ;)
Go to the top of the page
 
+Quote Post
редактор
сообщение Apr 14 2011, 11:45
Сообщение #15


Местный
***

Группа: Участник
Сообщений: 356
Регистрация: 9-06-07
Пользователь №: 28 315



Без разбора схемы обсуждение некорректно.
Если внешнее ПЗУ содержит только программу, то младшие 8К не используются, поскольку они выбираются из внутренней ПЗУ. Контроллер стартует оттуда (сигнал работы АНТОХА уточнял), не будет же контроллер на ходу его переключать для выбора внешнего и внутреннего ПЗУ для младших 8К. Это совсем круто.
Значит младшие 8К внешнего ПЗУ не содержат код.
если они содержат данные, то должна быть организована фоннеймановская архитектура, где код и данные объеденены. Если этого нет, то младшие 8К внешней ПЗУ вообще мусор.
Так я думаю.
P.S. Может и не прав, конечно.


--------------------
Хорошую систему делают из стандартных блоков нестандартно мыслящие инженеры.
Go to the top of the page
 
+Quote Post

2 страниц V   1 2 >
Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 27th July 2025 - 17:27
Рейтинг@Mail.ru


Страница сгенерированна за 0.01513 секунд с 7
ELECTRONIX ©2004-2016