|
О подходах к программированию, Вынесено из темы "Какой-то бред..." |
|
|
|
Jan 3 2008, 00:47
|

Местный
  
Группа: Свой
Сообщений: 222
Регистрация: 9-06-07
Пользователь №: 28 317

|
Цитата(IgorKossak @ Jan 2 2008, 23:07)  Для тех, кто читает не всё: порты - по Atmel (default value); глобальные переменные - по АНСИ СИ. Да действительно, прежде всего стоит смотреть в даташит, какие начальные значения у регистров - тут уж посыпаю голову пеплом. Насчет ANSI C, то он насколько я знаю убнуляет в том числе автоматические переменные. В любом случае, когда не уверен, то лучше сделать все вручную. Цитата(HCHUNTER @ Jan 2 2008, 23:36)  Цитата При этом не забудьте убрать цикл "while (1)" из мейна. А это для чего? что оно мне даст? куда же я тогда возвращаться-то буду... в "никуда" получается... Вы в цикле выставляете ногу порта в еденицу. Я прежде всего имел ввиду убрать именно это. Насчет возврата в никуда, не знаю как в CV, но в AVR GCC нет необходимсоти вставлять чечный цикл. Цитата(HCHUNTER @ Jan 2 2008, 23:36)  Цитата Хочу заметить, что всякие задержки в прерываниях (наподобее delay_us) крайне не рекоммендуются, прерывание - это критическая часть кода, из которого следует выходить как можно скорее. Вот это мне тоже, кстати, не совсем понятно... Звучит как заученная фраза из книжек. А если мне нужно по возникновении прерывания выполнить массу всего? Что мне тогда делать...? Тут уж я научен горьким опытом. Прерывание опасно тем, что создает многопоточность, но при этом с непресдсказуемым вызовом "потоков". Если нужно выполнить какое-то критичное по времени действие, то делайте его в прерывании; если вы к примеру семплируете звук в реалтайме, то обрабатывайте событие АЦП то-же в прерывании. В прерывании должен содержаться минимальный код, в крайнем случае, код прерывания должен выполняться минимальное время. Во всех остальных случаях в мейне должен крутиться цикл с провркой флагов. Притом, не забывайте, что для всез прерываний есть аппаратные флаги, таким образом, нет необходимсоти делать софтовый флаг, который будет устанавливаться в прерывании. Насчет инициализации таймеров, могу сослать на соседнюю тему - http://electronix.ru/forum/index.php?showtopic=41239# - там я писал про инициализацию таймера для отсчета секунды. То, что там написано, конечно, не истина в последней инстанции, но, во всяком случае, у меня работает.
|
|
|
|
|
Jan 3 2008, 16:17
|
Гуру
     
Группа: Свой
Сообщений: 10 920
Регистрация: 5-04-05
Пользователь №: 3 882

|
Цитата(Aesthete Animus @ Jan 3 2008, 05:47)  Насчет ANSI C, то он насколько я знаю убнуляет в том числе автоматические переменные. Ошибаетесь. Автоматические это то же что и локальные переменные, выделяемая для них память находится на стеке или в регистрах. Они и еще регистровые (register) переменные не инициализируются нулями в отличие от глобальных и статических (static). Цитата(Aesthete Animus @ Jan 3 2008, 05:47)  В любом случае, когда не уверен, то лучше сделать все вручную. А вот это правильно.
|
|
|
|
|
Jan 3 2008, 18:28
|

Местный
  
Группа: Свой
Сообщений: 222
Регистрация: 9-06-07
Пользователь №: 28 317

|
Цитата(rezident @ Jan 3 2008, 19:17)  Они и еще регистровые (register) переменные не инициализируются нулями в отличие от глобальных и статических (static). Почитал документацию... Посыпаю голову пеплом... Цитата(zltigo @ Jan 3 2008, 20:23)  Совершенно не правильно  Когда не уверен, надо уверенность и твердость знаний приобретать а не заниматься инициализаций всего, чего попало неуверенными руками. Вот если бы все было заранее известно, что и как работает, то все было бы просто. В том и возникает сложность нашей работы, что постоянно существует некоторая неопределенность задачи. Единственный признак мастерства - это умение сужать эту неопределенность. Иногда такое такое как у Автора обнуление как раз помогает сузить круг поиска. А твердость знаний приобретается отнюдь не зубрежкой документации - все в конце концов делают все те же "неуверенные руки".
|
|
|
|
|
Jan 3 2008, 23:38
|

Гуру
     
Группа: Свой
Сообщений: 13 372
Регистрация: 27-11-04
Из: Riga, Latvia
Пользователь №: 1 244

|
Цитата(rezident @ Jan 4 2008, 01:24)  Скобки в сложных выражениях и (ре)инициализация переменных никогда лишними не бывают. Разные вещи. Скобки вещь вполне безобидная, проблем для конечного результата не вызывают никаих, при не слишком уж чрезмерном использовании читабельность скорее повышают. В противоположность этому, инициализация того, чего не нужно и там где не нужно это лишний код и сбивание с толку читающего исходник человека с нормальным уровнем квалификации. Видишь какой-нибудь "узор" и внимание отлекается, начинаешь думать - зачем? может какая-то наихитрейшая хитрость?.... а ничего на самом деле нет - масло маслянное, мусор......
--------------------
Feci, quod potui, faciant meliora potentes
|
|
|
|
|
Jan 4 2008, 14:06
|

Местный
  
Группа: Свой
Сообщений: 222
Регистрация: 9-06-07
Пользователь №: 28 317

|
Цитата(zltigo @ Jan 3 2008, 21:45)  Зачем зубрежкой? Зубрежки категорически не надо. Так почитать всю перед сном разок для общей ориентировки. Ну а потом чтение избранных мест документации при необходимости и в случае возникновения неуверенности. Насчет зубрежки - выразился я несколько некорректно. Я говорю лишь о том, что нельзя все охватить на первом этапе. Всегда есть некоторая неопределенность, и в документации, право, тоже бывают ошибки. Поэтому подобные избыточные инициализации не всегда бывают лишними, подчас они следуют не из незнания документации, а из элементарного здравого смысла. Они подчас убирают ту самую неуверенность. Будьте уверены, когда Автор разберется в этом таймере, он пройдется по коду и удалит все лишнее. Ей богу, развели мы тут очередные религиозные споры...
Сообщение отредактировал Aesthete Animus - Jan 4 2008, 14:08
|
|
|
|
|
Jan 4 2008, 18:36
|

Гуру
     
Группа: Свой
Сообщений: 13 372
Регистрация: 27-11-04
Из: Riga, Latvia
Пользователь №: 1 244

|
Цитата(Aesthete Animus @ Jan 4 2008, 16:06)  Ей богу, развели мы тут очередные религиозные споры... Это для этой темы оффтопик, конечно, но отнюдь не религиозные споры. Отнюдь. С этим я, как модератор, справлюсь - выделю в отдельную тему. Цитата Будьте уверены, когда Автор разберется в этом таймере, он пройдется по коду и удалит все лишнее. Да? Я достаточно повидал всякого и могу утверждать, что с несоиразмеримо большей вероятностью произойдет все с точностью до наоборот  . Возьмем, например, Вас, как Автора. Вот Ваш небольшой, и соответственно легко обозримый кусочек исходника: Код Лично я делаю так: /****************************************************** * Преобразует в строку length младших битов * * слова word. Строка dest должна иметь размер * * по меньшей мере length + 1 * ******************************************************/ char* bitwise(uint32_t word, char* dest, uint8_t length) { register uint8_t i; for (i = 0; i < length; i++) dest[length - i - 1] = word & (1UL << i) ? '1' : '0'; dest[length] = '\0'; return dest; } Только бога ради, не воспринимайте ниженаписанное, как личный наезд - просто иллюстрация к утверждению, что "Автор потом...". Вы написали некую, функцию, добились ее рабоспособности и даже выложили на всеобщее обозрение. Однако не верю, что Вы после того, как "заработало" хоть несколько раз ее просмотрели, ибо в противном случае она просто обязана была выглядеть иначе. Например, так: Код char* bitwise(uint32_t word, char* dest, uint8_t length) { dest += length; *dest = '\0'; while( length-- ) { *--dest = (word & 1) + '0'; word >>= 1; } return dest; } Результат такой "чистки" в несколько раз меньший код, в том числе и в цикле и соответственно быстродействие. Я совершенно не берусь утверждать, что написанное мною является самым эффективным для AVR платформы - я просто прочитал и поправил на лету явное бросающееся в глаза. Еще раз - это не "наезд", такие-же ляпы найти можно у абсолютно любого - это просто констатация факта, что "откладывание на потом" совершенно губительно.
--------------------
Feci, quod potui, faciant meliora potentes
|
|
|
|
|
Jan 4 2008, 21:44
|

Местный
  
Группа: Свой
Сообщений: 222
Регистрация: 9-06-07
Пользователь №: 28 317

|
Цитата(zltigo @ Jan 4 2008, 21:36)  Только бога ради, не воспринимайте ниженаписанное, как личный наезд - просто иллюстрация к утверждению, что "Автор потом...". Вы написали некую, функцию, добились ее рабоспособности и даже выложили на всеобщее обозрение. Однако не верю, что Вы после того, как "заработало" хоть несколько раз ее просмотрели, ибо в противном случае она просто обязана была выглядеть иначе. Например, так: Код char* bitwise(uint32_t word, char* dest, uint8_t length) { dest += length; *dest = '\0'; while( length-- ) { *--dest = (word & 1) + '0'; word >>= 1; } return dest; } Результат такой "чистки" в несколько раз меньший код, в том числе и в цикле и соответственно быстродействие. Я совершенно не берусь утверждать, что написанное мною является самым эффективным для AVR платформы - я просто прочитал и поправил на лету явное бросающееся в глаза. "Не воспринимайте ниженаписанное, как личный наезд". Боже упаси - мы же с вами в приличном обществе находимся и, я думаю, никто не собирается устраиавть здесь "разборок". Тем не менее, перчатка в мой адрес брошена и я не могу не ответить по этому поводу. Да, Ваш код более короткий и наверное более быстрый, написан он надо сказать изящно. Но скажите мне, так ли уж страшна потеря десятка операций в данном случае. Когда я пишу код я прежде всего руководствуюсь его выразительностью. Даже в данном случае, проще понять что происходит у меня в коде, нежели у Вас. Я противник запутанных выражений, возможностью коих нас наградил Риччи с сотоварищами и избегаю конструкций наподобее dest[++i] или while(length--). Ежели для решения задачи так страшна потеря этих нескольких тактов, то наверное надо не заниматься бесконечной отладкой каждой фукнции, а возможно, следует пересмотреть всю архитектуру системы. Кстати, эту фукнцию я приводил в теме, до конца тему не прочитав и не поняв сути. За то прошу меня простить. Цитата(zltigo @ Jan 4 2008, 21:36)  Такие-же ляпы найти можно у абсолютно любого - это просто констатация факта, что "откладывание на потом" совершенно губительно. Но нельзя пытаться охватить сразу! Нельзя зарываться в мелочях, ибо дьявол в них обитает! Пытаться все охватить сразу не менее губительно, нежели то, о чем Вы говорите. Изыски в решении задачи подчас просто необходимы, но не надо ими злоупотреблять. Решение должно быть "грубым" (в терминах грубых систем), платформа для этого - избыточной. Я к примеру никогда не использую ресурсы контроллера более чем на 20 процентов (за исключением SRAM`ма) и не советую эту цифру поднимать выше 80 процентов. Если система перестает работать из-за паразитной задержки в несколько тактов, то эта система "жесткая" и ее стоит изменить.
|
|
|
|
|
Jan 4 2008, 22:59
|

Гуру
     
Группа: Свой
Сообщений: 13 372
Регистрация: 27-11-04
Из: Riga, Latvia
Пользователь №: 1 244

|
Цитата(Aesthete Animus @ Jan 4 2008, 23:44)  ..написан он надо сказать изящно. Он не написан изящно - вполне лобовой естественный код. Писался без раздумий. Просто без путанных избыточных конструкций. Цитата Даже в данном случае, проще понять что происходит у меня в коде, нежели у Вас. Вы очень заблуждаетесь. Я потратил на обозрение кода в той ветке достаточно много времени (много больше, чем на написание более простого) пытаясь вникнуть в суть. Компилятор тоже Вас плохо понял - сравниваем: Код 132 char* bitwise(unsigned long word, char* dest, unsigned char length) \ bitwise: 133 { \ 00000000 93BA ST -Y, R27 \ 00000002 2E3A MOV R3, R26 \ 00000004 2F79 MOV R23, R25 \ 00000006 2E28 MOV R2, R24 \ 00000008 01C8 MOVW R25:R24, R17:R16 \ 0000000A 01D9 MOVW R27:R26, R19:R18 \ 0000000C 010A MOVW R1:R0, R21:R20 134 register unsigned char i; 135 for (i = 0; i < length; i++) \ 0000000E E050 LDI R21, 0 \ 00000010 2366 TST R22 \ 00000012 F0D9 BREQ ??bitwise_0 \ 00000014 01F0 MOVW R31:R30, R1:R0 \ 00000016 0FE6 ADD R30, R22 \ 00000018 1FF5 ADC R31, R21 \ 0000001A 9731 SBIW R31:R30, 1 136 dest[length - i - 1] = word & (1UL << i) ? '1' : '0'; \ ??bitwise_1: \ 0000001C E001 LDI R16, 1 \ 0000001E E010 LDI R17, 0 \ 00000020 E020 LDI R18, 0 \ 00000022 E030 LDI R19, 0 \ 00000024 2F45 MOV R20, R21 \ 00000026 ........ CALL ?L_SHL_L03 \ 0000002A 2308 AND R16, R24 \ 0000002C 2319 AND R17, R25 \ 0000002E 232A AND R18, R26 \ 00000030 233B AND R19, R27 \ 00000032 2B01 OR R16, R17 \ 00000034 2B02 OR R16, R18 \ 00000036 2B03 OR R16, R19 \ 00000038 F011 BREQ ??bitwise_2 \ 0000003A E301 LDI R16, 49 \ 0000003C C001 RJMP ??bitwise_3 \ ??bitwise_2: \ 0000003E E300 LDI R16, 48 \ ??bitwise_3: \ 00000040 8300 ST Z, R16 \ 00000042 9553 INC R21 \ 00000044 9731 SBIW R31:R30, 1 \ 00000046 1756 CP R21, R22 \ 00000048 F348 BRCS ??bitwise_1 137 dest[length] = '\0'; \ ??bitwise_0: \ 0000004A E000 LDI R16, 0 \ 0000004C 01F0 MOVW R31:R30, R1:R0 \ 0000004E 0FE6 ADD R30, R22 \ 00000050 1FF0 ADC R31, R16 \ 00000052 8300 ST Z, R16 138 return dest; \ 00000054 0180 MOVW R17:R16, R1:R0 \ 00000056 2D82 MOV R24, R2 \ 00000058 2F97 MOV R25, R23 \ 0000005A 2DA3 MOV R26, R3 \ 0000005C 91B9 LD R27, Y+ \ 0000005E 9508 RET 139 } и вполне понятный мне и много более понятный компилятору код: Код 143 char* bw(unsigned long word, char* dest, char length) \ bw: 144 { 145 dest += length; \ 00000000 E070 LDI R23, 0 \ 00000002 0F46 ADD R20, R22 \ 00000004 1F57 ADC R21, R23 146 *dest = '\0'; \ 00000006 01FA MOVW R31:R30, R21:R20 \ 00000008 8370 ST Z, R23 \ 0000000A 2366 TST R22 \ 0000000C F069 BREQ ??bw_0 \ ??bw_1: \ 0000000E 956A DEC R22 147 while( length-- ) 148 { *--dest = (word & 1) + '0'; \ 00000010 2F70 MOV R23, R16 \ 00000012 7071 ANDI R23, 0x01 \ 00000014 5D70 SUBI R23, 208 \ 00000016 01FA MOVW R31:R30, R21:R20 \ 00000018 9372 ST -Z, R23 \ 0000001A 01AF MOVW R21:R20, R31:R30 149 word >>= 1; \ 0000001C 9536 LSR R19 \ 0000001E 9527 ROR R18 \ 00000020 9517 ROR R17 \ 00000022 9507 ROR R16 150 } \ 00000024 2366 TST R22 \ 00000026 F799 BRNE ??bw_1 151 return( dest ); \ ??bw_0: \ 00000028 018A MOVW R17:R16, R21:R20 \ 0000002A 9508 RET 152 } Разница отнюдь не в поминаемые "несколько тактов" и даже не десятков тактов. Цитата Я противник запутанных выражений... В оценке степени запутанности мы с компилятором и Вы диаметрально расходимся  Цитата ..а возможно, следует пересмотреть всю архитектуру системы. Слова, слова, слова,... правильные слова. Плохо, когда даже правильными словами начинают манипулировать. Цитата Кстати, эту фукнцию я приводил в теме, до конца тему не прочитав и не поняв сути. За то прошу меня простить. Это не принципиально - я совсем мельком взглянул на ту тему и зацепившись взглядом за непонятное было подумал, что есть что-то интересное..... Цитата Я к примеру никогда не использую ресурсы контроллера более чем на 20 процентов (за исключением SRAM`ма) и не советую эту цифру поднимать выше 80 процентов. Ресурсов контроллера должно хватать для обеспечения функционирования критических задач при пиковой нагрузке. Все остальные при этом могут и подождать и/или иметь допустимые потери в обслуживании. А почему для SRAM сделано исключение зачем-то?  Гулять, так гулять! Если системе оставляют 80% на "всякий случай", то это свидетельстует об одном - разработчик так-же, как и в лучае инициализации на "всякий случай" чего не поподя (с чего эта ветка и началась) не имеет твердого понятия о том, что делает. Вот такое закономерное  движение от непонимания-неуверенности в простом к непониманию-неуверенности в сложном  . Цитата Если система перестает работать из-за паразитной задержки в несколько тактов, то эта система "жесткая" и ее стоит изменить. Об использовании совершенно правильных слов уже писал выше.
--------------------
Feci, quod potui, faciant meliora potentes
|
|
|
|
|
Jan 6 2008, 17:17
|

Местный
  
Группа: Свой
Сообщений: 222
Регистрация: 9-06-07
Пользователь №: 28 317

|
Цитата(zltigo @ Jan 5 2008, 01:59)  Разница отнюдь не в поминаемые "несколько тактов" и даже не десятков тактов. И что мы теряем? Надо оптимизировать не какие-то проходные функции, а действительно критический код. Цитата(zltigo @ Jan 5 2008, 01:59)  В оценке степени запутанности мы с компилятором и Вы диаметрально расходимся  Насчет понятности Вашего кода - это тоже спорно. Я не привык думать в терминах языка программирования, и в моем случае это правильно. Я не хочу зацикливаться в мелочях, которые ни на что не влияют. Смотрю на Вашу строчку (word & 1) + '0' и думаю, зачем такая "наихитрейшая хитрость"? Для меня подобные вещи не более чем изыски, которых я избегаю в практической работе. Вам, я думаю, понравится такой код  Код #include <stdio.h>
main(argc, argv) int argc; char **argv; { while (*argv != argv[1] && (*argv = argv[1]) && (argc = 0) || (*++argv && (**argv && ((++argc)[*argv] && (**argv <= argc[*argv] || (**argv += argc[*argv] -= **argv = argc[*argv] - **argv)) && --argv || putchar(**argv) && ++*argv--) || putchar(10)))); } Цитата(zltigo @ Jan 5 2008, 01:59)  А почему для SRAM сделано исключение зачем-то?  Гулять, так гулять! Если системе оставляют 80% на "всякий случай", то это свидетельстует об одном - разработчик так-же, как и в лучае инициализации на "всякий случай" чего не поподя (с чего эта ветка и началась) не имеет твердого понятия о том, что делает. Вот такое закономерное  движение от непонимания-неуверенности в простом к непониманию-неуверенности в сложном  . На моей предыдущей работе были довольно специфичные задачи. У нас никогда не стоял вопрос цены контроллера. Если не хватает Flash памяти, используем более емкий контроллер (например мега128). Не хватает SRAM`а - подключаем внешний. Нужно производить много вычислений с плавающей точкой - переходим на ARM, который имеет сопроцессор. Если бы мы пытались вжать все скажем в мегу32 и тем самым тратили время на бесконечную оптимизацию, мы бы не могли делать того, что делаем. Повторяю, решение должно быть грубым! По крайней мере у меня, никогда не известна конечная задача и постоянно имеется неопределенность. Из этого постоянно приходится закладывать избыточность платформы. Можно оптимизировать каждую функцию, но это совершенно иной уровень задачи, как правило стоят проблемы на много более верхнего уровня, которые нельзя решить, если мы будем зарываться в каждой мелочи и экономить каждые двадцать, тридцать тактов. Такие потери обычно не критичны! Сейчас я временно работаю в другой организации. Здесь задачи порядком по проще, и определенность другого рода - я не знаю, что еще начальник захочет, чтобы я впихнул в контроллер. Здесь мне пришлось столкнуться именно с проблемой SRAM`а - решено перейти на другой контроллер. Поэтому и делаю из личных ощущений такое исключение в этом отношении. Цитата(zltigo @ Jan 5 2008, 01:59)  Ресурсов контроллера должно хватать для обеспечения функционирования критических задач при пиковой нагрузке. Все остальные при этом могут и подождать и/или иметь допустимые потери в обслуживании. Я это слышу как все те же "правильные слова". Возможно Вы в это вкладываете какой-то особый философский смысл, который я со своим мировосприятием не чуствую.
|
|
|
|
|
Jan 6 2008, 18:38
|

Гуру
     
Группа: Свой
Сообщений: 13 372
Регистрация: 27-11-04
Из: Riga, Latvia
Пользователь №: 1 244

|
Цитата(Aesthete Animus @ Jan 6 2008, 19:17)  И что мы теряем? Надо оптимизировать не какие-то проходные функции, а действительно критический код. Вы дважды не обратили внимание на главное, хотя я прямо об этом писал - приведенная мной функция ни в коей мере не претендует на звание "оптимизированной". Просто нормально естесвенно для "C" написанная функция. Так сказать стандартный уровень ремесла. Отсутствие базисного уровня владения языком невозможно прикрыть обширными размышлениями на темы абстрактного программирования. Цитата Я не привык думать в терминах языка программирования.... Не думайте - не надо - уровни абстракции должны соответствовать задаче. Но излагать результаты полета мысли приходится на языке. Не важно на каком - "C", русском.... Я могу в душе быть великим поэтом, но если результаты своих поэтических размышлений я смогу изложить только на уровне "моя-твоя-непонимай", то оценить это не сможет никто. Цитата(Aesthete Animus @ Jan 6 2008, 19:17)  ....который я со своим мировосприятием не чуствую. Да, я это понял  .
--------------------
Feci, quod potui, faciant meliora potentes
|
|
|
|
|
Jan 6 2008, 20:35
|
deleted
   
Группа: Свой
Сообщений: 555
Регистрация: 28-08-05
Пользователь №: 8 024

|
Как показалось, эта ветка скорей философская. Кому нужны длиннющие посты?, нужно кратко, и может ,это и тавтология, лаконично сформулировать вопрос. Кто знает, ответит. Короче, принцип KISS желательно блюсти , ведь потенциально могуще помочь, тратят свое время, хотя бы на чтение...
|
|
|
|
|
Jan 6 2008, 20:49
|

Местный
  
Группа: Свой
Сообщений: 222
Регистрация: 9-06-07
Пользователь №: 28 317

|
Ей богу, я уже начинаю терять нить нашего с Вами спора. Или для вас это повод сказать, какой Вы профессионал, а все остальные ничего не понимают? Цитата(zltigo @ Jan 6 2008, 21:38)  Отсутствие базисного уровня владения языком невозможно прикрыть обширными размышлениями на темы абстрактного программирования Вы меня обвиняете в отсутствии базисного владения языка, или это абстрактное изречение? Если да, то могу ответить, что для решения поставленных задач мне этого хватает. А иначе, что вы считаете критерием должного уровня владения языка? Стандартный уровень ремесла говорите? Ну чтож, будьте ремесленником и решайте задачи, как вот такую-то функцию написать по всем правилам языка Си, чтобы она была как можно быстрее и меньше - что-нибудь нестандартное, сложное и интересное оставьте нам. Цитата(zltigo @ Jan 6 2008, 21:38)  Вы дважды не обратили внимание на главное Вы тоже не поняли моей мысли. Именно Вы назвали тему "О подходах к программированию", но при этом все Ваши рассуждения строятся на основе критики отдельно взятой функции. Я из поста в пост говорю, что нельзя зарываться в мелочях и если функция работает и отвечает требованиям задачи, то лучше так и оставить! Я говорю о том, что избыточный код иногда исключает сомнения и сужает ту самую неопределенность, о которой я говорил уже не раз. Но на этот свой тезис я так и не получаю ответа: если Вы именно с этим моим подходом не согласны хочу увидеть критику именно подхода! 2 INT1Тут, видите ли, очередной спор о проблеме мироздания - помочь врядли сможете....
|
|
|
|
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|