18.06.2019, 13:13 [+3 UTC]
в нашей команде: 3 711 чел. | участники онлайн: 12 (рекорд: 21)

:: РЕГИСТРАЦИЯ

задать вопрос

все разделы

правила

новости

участники

доска почёта

форум

блоги

поиск

статистика

наш журнал

наши встречи

наша галерея

отзывы о нас

поддержка

руководство

Версия системы:
7.77 (31.05.2019)
JS-v.1.34 | CSS-v.3.35

Общие новости:
28.04.2019, 09:13

Форум:
18.06.2019, 08:32

Последний вопрос:
17.06.2019, 15:06
Всего: 149828

Последний ответ:
18.06.2019, 12:04
Всего: 258619

Последняя рассылка:
17.06.2019, 20:45

Писем в очереди:
1

Мы в соцсетях:

Наша кнопка:

RFpro.ru - здесь вам помогут!

Отзывы о нас:
18.01.2012, 16:34 »
Даровко Антон Владимирович
Я посмотрел Ваш ответ и оценил его на отлично. [вопрос № 185202, ответ № 269623]
26.07.2010, 13:54 »
Batman
Фактически выбрал вашу конфигурацию. Но вы не обосновали свой выбор, как vvl и Victor Pyrlik. И не "уговорили" меня перейти на DDR3 ))) [вопрос № 179563, ответ № 262628]

РАЗДЕЛ • Assembler

Создание программ на языке Assembler.

[администратор рассылки: Лысков Игорь Витальевич (Старший модератор)]

Лучшие эксперты в этом разделе

Коцюрбенко Алексей Владимирович
Статус: Модератор
Рейтинг: 275
Зенченко Константин Николаевич
Статус: Старший модератор
Рейтинг: 240
Лысков Игорь Витальевич
Статус: Старший модератор
Рейтинг: 100

Перейти к консультации №:
 

Консультация онлайн # 195817
Раздел: • Assembler
Автор вопроса: MarkKnopfler (Посетитель)
Отправлена: 06.06.2019, 16:14
Поступило ответов: 1

Здравствуйте! Прошу помощи с реализацией задачи.
Изменить дату и время создания файла MYFILE.txt и вывести их старые и новые значения на экран.
1. Формат программы: COM - программа
2. Ввод с клавиатуры: средствами DOS
3. Вывод на экран: в текстовом режиме
4. Динамическое распределение памяти: определение размера программы.
Надеюсь на Вашу помочь! Заранее благодарен!

Состояние: Консультация закрыта

Ответ # 278287 от Лысков Игорь Витальевич (Старший модератор)


Здравствуйте, MarkKnopfler!
Держите программу... Можно по-разному сделать, я сделал так...
Комментариев не писал, разбирайтесь самостоятельно... Будут вопросы, спрашивайте в мини-форуме.
Не забывайте, программа в формате COM (Ваш пример - EXE)
Для преобразования байта - двоичного числа в две цифры использована команда AAM
При вводе даты/времени ожидается ввод только в ожидаемом виде и проводится проверка на корректность.
Единственная неточность: день проверяется всегда на 31. Надо проверять на максимальный для каждого месяца
и с учетом високосного года. Этим я пренебрег для простоты :)
И наконец, для чего пункт 4. Динамическое распределение памяти?

Код (Assembler) :: выделить код
TITLE	PROG
	.MODEL	tiny
	.data
filename	DB	'MYFILE.txt',0
Error 		db 	13,10,'Error!',13,10,'$'
MessageOld	db	'Old $'
MessageNew	db	0dh,0ah,'New $'
MessageDateTime	db	'date: '
day_pos		db	'xx.'
month_pos	db	'xx.'
year_pos	db	'xxxx, time:'
hours_pos	db	'xx:'
minutes_pos	db	'xx:'
seconds_pos	db	'xx',0dh,0ah,'$'

MessageEnterDate	db	'Enter date (dd.mm.yyyy): $'
MessageEnterTime	db	0dh,0ah,'Enter time (hh.mm.ss): $'

InBuffer	db	128
InCount		db	?
InData		db	128 dup (?)

	.CODE   
	.186
	ORG	100H
BEGIN:
	mov	ah, 3dh 
	mov	al, 0
	lea	dx, filename 
	int	21h
	jc	MError

	mov	bx, ax

	mov	ax, 5700h	;read time/date of file
	int	21h

	lea	si, MessageOld
	call	PrintTimeDate

	call	EnterNewTimeDate
	jc	MError

	mov	ax, 5701h 
	int	21h

	lea	si, MessageNew
	call	PrintTimeDate
	
	mov	ah, 3eh
	int	21h
	jnc	NoError
MError:
	lea	dx, Error
	mov	ah,09h
	int	21h
NoError:
	mov	ax,4c00h
	int	21h

PrintTimeDate	proc	near
	push	dx
	mov	dx, si
	mov	ah, 9
	int	21h
	pop	dx
	push	dx
	push	cx
	mov	ax, dx
	and	ax, 001fh
	aam
	or	ax, '00'
	mov	day_pos, ah
	mov	day_pos+1, al

	mov	ax, dx
	and	ax, 01e0h
	shr	ax, 5
	aam
	or	ax, '00'
	mov	month_pos, ah
	mov	month_pos+1, al

	mov	ax, dx
	shr	ax, 9
	add	ax, 1980
	mov	cl, 100
	div	cl
	push	ax
	aam
	or	ax, '00'
	mov	year_pos, ah
	mov	year_pos+1, al
	pop	ax
	mov	al, ah
	aam
	or	ax, '00'
	mov	year_pos+2, ah
	mov	year_pos+3, al

	pop	cx
	mov	ax, cx
	shr	ax, 11
	aam
	or	ax, '00'
	mov	hours_pos, ah
	mov	hours_pos+1, al

	mov	ax, cx
	and	ax, 07e0h
	shr	ax, 5
	aam
	or	ax, '00'
	mov	minutes_pos, ah
	mov	minutes_pos+1, al

	mov	al, cl
	and	al, 1fh
	shl	al, 1
	aam
	or	ax, '00'
	mov	seconds_pos, ah
	mov	seconds_pos+1, al

	lea	dx, MessageDateTime
	mov	ah, 9
	int	21h
	pop	dx
	ret
PrintTimeDate	endp

EnterNewTimeDate	proc	near
	lea	dx, MessageEnterDate
	mov	ah, 9
	int	21h
	lea	dx, InBuffer
	mov	ah, 0ah
	int	21h
	cmp	byte ptr InCount, 10
	jne	EnterNewTimeDate_error

	lea	si, InData
	call	GetNum2
	jc	EnterNewTimeDate_error
	cmp	ax, 31
	jg	EnterNewTimeDate_error
	test	ax, ax
	jz	EnterNewTimeDate_error
	mov	di, ax

	lea	si, InData+3
	call	GetNum2
	jc	EnterNewTimeDate_error
	cmp	ax, 12
	jg	EnterNewTimeDate_error
	test	ax, ax
	je	EnterNewTimeDate_error
	shl	ax, 5
	or	di, ax

	lea	si, InData+6
	call	GetNum4
	jc	EnterNewTimeDate_error
	sub	ax, 1980
	jl	EnterNewTimeDate_error
	cmp	ax, 119
	jg	EnterNewTimeDate_error
	shl	ax, 9
	or	di, ax

	lea	dx, MessageEnterTime
	mov	ah, 9
	int	21h
	lea	dx, InBuffer
	mov	ah, 0ah
	int	21h

	cmp	byte ptr InCount, 8
	jne	EnterNewTimeDate_error

	lea	si, InData
	call	GetNum2
	jc	EnterNewTimeDate_error
	cmp	ax, 23
	jg	EnterNewTimeDate_error
	shl	ax, 11
	mov	cx, ax

	lea	si, InData+3
	call	GetNum2
	jc	EnterNewTimeDate_error
	cmp	ax, 59
	jg	EnterNewTimeDate_error
	shl	ax, 5
	or	cx, ax

	lea	si, InData+6
	call	GetNum2
	jc	EnterNewTimeDate_error
	cmp	ax, 59
	jg	EnterNewTimeDate_error
	shr	ax, 1
	or	cx, ax

	mov	dx, di
	clc
	ret
EnterNewTimeDate_error:
	stc
	ret
EnterNewTimeDate	endp

GetNum4	proc
	call	GetNum2
	jc	GetNum4_ret
	mov	bp, 100
	mul	bp
	push	ax
	call	GetNum2
	pop	bp
	jc	GetNum4_ret
	add	ax, bp
	clc
GetNum4_ret:
	ret
GetNum4	endp

GetNum2	proc
	lodsb
	cmp	al, '0'
	jl	GetNum2_error
	cmp	al, '9'
	jg	GetNum2_error
	and	al, 0fh
	mov	ah, 10
	mul	ah
	mov	dx, ax
	lodsb
	cmp	al, '0'
	jl	GetNum2_error
	cmp	al, '9'
	jg	GetNum2_error
	and	ax, 0fh
	add	ax, dx
	clc
	ret
GetNum2_error:
	stc
	ret
GetNum2	endp

END BEGIN


Консультировал: Лысков Игорь Витальевич (Старший модератор)
Дата отправки: 07.06.2019, 19:45

5
нет комментария
-----
Дата оценки: 09.06.2019, 17:58

Рейтинг ответа:

+2

[подробно]

Сообщение
модераторам

Отправлять сообщения
модераторам могут
только участники портала.
ВОЙТИ НА ПОРТАЛ »
регистрация »

Мини-форум консультации № 195817

Лысков Игорь Витальевич
Старший модератор

ID: 7438

# 1

= общий = | 06.06.2019, 18:53 | цитировать цитировать  | профиль профиль  |  отправить письмо в личную почту пейджер
MarkKnopfler:

Помочь, в смысле сделать за Вас? smile
Чего Вы достигли в написании программы?

=====
"Если вы заметили, что вы на стороне большинства, —
это верный признак того, что пора меняться." Марк Твен

MarkKnopfler
Посетитель

ID: 403112

# 2

= общий = | 06.06.2019, 23:55 | цитировать цитировать  | профиль профиль  |  отправить письмо в личную почту пейджер

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

TITLE PROG
.MODEL SMALL
.data
filename DB 'C:\LOL\MYFILE.txt',0
handle dw ?
sec dw 8/2
min dw 25*32 
hour dw 19*2048
day dw 16
mon dw 8*32
year dw 15*512
Error db 'Error!',13,10,'$'
.CODE	
ORG 100H
BEGIN:
mov ah,3dh 
mov al,0
lea dx, filename 
int 21h
MOV handle,ax
jc MError

mov ah,57h 
mov al,1 
mov bx,handle 
mov cx,0 
OR CX,sec 
OR CX,min
OR CX,hour
mov DX,0 
OR DX,day 
OR DX,mon
OR DX,year
INT 21H

mov ah,3eh
int 21h
jnc NoError

MError:
lea dx, Error
mov ah,09h
int 21h

NoError:
mov ax,4c00h
int 21h
END BEGIN

MarkKnopfler
Посетитель

ID: 403112

# 3

= общий = | 09.06.2019, 18:31 | цитировать цитировать  | профиль профиль  |  отправить письмо в личную почту пейджер

Добрый день!

Прошу прощения за относительно нескорый ответ. Пытался разобраться в Вашей программе: что-то получилось понять, а что-то нет. В первую очередь хотел бы выразить огромную благодарность за Ваш труд. Восхищён Вашими умениями!

Что касается самой программы, то хотелось бы услышать объяснение по нескольким моментам, будьте добры:
1. Каким образом происходит преобразование значения из регистра CX в привычный формат времени? Можно на каком-нибудь примере показать? С датой преобразования понятны, а вот со временем...
2. Для чего используется в программе InData (и в частности инструкции: lea si, InData / lea si, InData+3 / lea si, InData+6)?
3. Что происходит в процедурах GetNum2 и GetNum4? Интуитивно понял, что они позволяют записать 2 цифры и 4 (для года) соответственно, а вот детали — голова кругом smile

И отвечая на Ваш вопрос о 4-м пункте — для подсчёта размера программы. Т.е. программа должна выводить его. В каких справочниках / учебниках / источниках об этом можно прочитать?

И последний вопрос: как можно финансово поддержать ваш проект? Не нашёл соответствующего раздела smile

-----
Последнее редактирование 09.06.2019, 18:33 MarkKnopfler (Посетитель)

Лысков Игорь Витальевич
Старший модератор

ID: 7438

# 4

 +1 
 
= общий = | 10.06.2019, 12:08 | цитировать цитировать  | профиль профиль  |  отправить письмо в личную почту пейджер
MarkKnopfler:

Есть вопросы - это замечательно smile Итак:
1) Формат времени файла в функциях ДОСа следующий (побитно):
CX = hhhhhmmm mmmsssss, где
hhhhh - часы, старшие 5 бит слова (0-23),
mmmmmm - минуты, 6 бит внутри слова (0-59),
sssss - секунды пополам, младшие 5 бит, (счет с точностью до 2 секунд, значение от 0 до 29)

Чтобы получить часы, делаем сдвиг вправо на 11 бит и получим число в младших битах слова
Чтобы получить минуты, сначала выделяем нужные биты, накладаем маску 07e0h и сдвигаем вправо на 5 бит (можно и наоборот, сначала сдвинуть, потом наложить маску 003fh)
Чтобы получить секунды, накладываем маску 001fh и умножаем на 2 (сдвигом влево на 1 бит)

2) InData является частью буфера, который используется при вводе при помощи функции 0ah:

Код (Assembler) :: выделить код
InBuffer   db   128  ;длина буфера
InCount      db   ? ;длина реально введенный данных
InData      db   128 dup (?) ;сами введенные данные

Дату програма ждет в виде DD.MM.YYYY, т.е.
день, как два байта в начаче буфера InData,
месяц, как два байта, начиная с адреса InData+3,
года, как четыре байта, начиная с адреса InData+6
Аналогично и время ждем в виде ЧЧ:ММ:СС
Поэтому перед вызовом функций GetNum2 и GetNum4 указываем адрес, где лежат введенные числа в виде ASCII символов цифр

3) Функция GetNum2 читает два десятичных разряда числа (предворительно превращая из символов в число) по адресу в SI и формирует из них число, умножая старший разряд на 10 и складывая с младшим
Функция GetNum4 вызывает два раза GetNum2, дабы получить столетие и год, затем столетие умножается на 100 и складывается с годом.

Небольшое замечание, касаемое года. В формате даты год считается от 1980 года (т.е. нулевой год - это год 1980). Поэтому при преобразования туда/сюда отнимается/добавляется 1980.

3) Перед подсчетом размера программы необходимо понимать следующее:
- для модели tiny данные размещаются за кодом, т.е. последний использованный адрес будет в конце сегмента данных
- сегменты выравниваются на границу слова. Т.е. сегмент данных будет с четного адреса. Другими словами, если длина сегмента кода нечетная, то будет добавлен один байт для выравнивания до четного адреса.
Итак, нам надо добавить две метки:
Код (Assembler) :: выделить код
InData      db   128 dup (?) 
 FINISH label byte ;метка в конце сегмента данных
и
Код (Assembler) :: выделить код
GetNum2	endp
FINISH_PRG: ;метка в конце сегмента кода
END BEGIN
Тогда длина программы получается, как:
Код (Assembler) :: выделить код
mov	ax, ((FINISH_PRG-BEGIN+1) and 0fffeh)+FINISH-filename
Т.е. считаем длину сегмента кода (с учетом выранивания!) и длину сегмента данных.
Может возникнуть вопрос: почему нельзя mov ax, FINISH-BEGIN? Нельзя, т.к. в разных сегментах.
И еще вопрос: как вывести полученную длину? Или как hex, либо как десятичное число. Оставляю на самостоятельную работу smile

Есть еще вариант: разместить данные в сегменте кода за кодом (для модели tiny так делается весьма часто).
Тогда, поставив метку за данными, получим длину, как разность между этой меткой и BEGIN

-----
Последнее редактирование 11.06.2019, 14:32 Лысков Игорь Витальевич (Старший модератор)

=====
"Если вы заметили, что вы на стороне большинства, —
это верный признак того, что пора меняться." Марк Твен

MarkKnopfler
Посетитель

ID: 403112

# 5

= общий = | 12.06.2019, 14:46 | цитировать цитировать  | профиль профиль  |  отправить письмо в личную почту пейджер
Лысков Игорь Витальевич:

Добрый день! Большое спасибо, доработал для программы подсчёт её размера. Изобразил блок-схему, предварительно исключив процедуры (вышло объёмнее, но для построения блок-схемы так легче). Проверьте последовательность выполнения всех этапов, пожалуйста, и в частности момент с некорректным вводом данных. Да и в целом, допускается ли в таком варианте изображать блок-схему? Спасибо!

-----
Последнее редактирование 12.06.2019, 14:55 Лысков Игорь Витальевич (Старший модератор)

Лысков Игорь Витальевич
Старший модератор

ID: 7438

# 6

= общий = | 12.06.2019, 14:50 | цитировать цитировать  | профиль профиль  |  отправить письмо в личную почту пейджер
MarkKnopfler:

Ну так показуем все, что сделано smile
Если надо, для загрузки на нащ сервер есть сервис мои файлы
Загружаем, кидаем сюда BBCode-ссылочку вида [url=http://rfpro.ru/d/...

=====
"Если вы заметили, что вы на стороне большинства, —
это верный признак того, что пора меняться." Марк Твен

Лысков Игорь Витальевич
Старший модератор

ID: 7438

# 7

= общий = | 12.06.2019, 14:56 | цитировать цитировать  | профиль профиль  |  отправить письмо в личную почту пейджер
MarkKnopfler:

А ссылки на картинки надо давать в виде [ img ]http://rfpro.ru/d/11605.jpg[/img ] (без пробелов) smile

=====
"Если вы заметили, что вы на стороне большинства, —
это верный признак того, что пора меняться." Марк Твен

MarkKnopfler
Посетитель

ID: 403112

# 8

= общий = | 12.06.2019, 14:57 | цитировать цитировать  | профиль профиль  |  отправить письмо в личную почту пейджер
Лысков Игорь Витальевич:



Не сразу разобрался smile

Изображение

Лысков Игорь Витальевич
Старший модератор

ID: 7438

# 9

= общий = | 12.06.2019, 14:59 | цитировать цитировать  | профиль профиль  |  отправить письмо в личную почту пейджер
MarkKnopfler:

Удобнее сразу показать... smile
Хорошо, смотрим блок-схему...

=====
"Если вы заметили, что вы на стороне большинства, —
это верный признак того, что пора меняться." Марк Твен

Лысков Игорь Витальевич
Старший модератор

ID: 7438

# 10

= общий = | 12.06.2019, 15:03 | цитировать цитировать  | профиль профиль  |  отправить письмо в личную почту пейджер
MarkKnopfler:

В целом, должно сойти. Может, разве что добавить открытие файла, перед проверкой, что он открыт.
И где вывод размера программы? Раз добавлено, надо учесть и в блок-схеме

=====
"Если вы заметили, что вы на стороне большинства, —
это верный признак того, что пора меняться." Марк Твен

Лысков Игорь Витальевич
Старший модератор

ID: 7438

# 11

= общий = | 12.06.2019, 15:07 | цитировать цитировать  | профиль профиль  |  отправить письмо в личную почту пейджер
MarkKnopfler:

Еще кое-что надо подправить:
Параллелограмм "Завершение программы" лишний.
И если введенные дата и время некорректны, то надо перейти на вывод сообщения об ошибке.

-----
Последнее редактирование 12.06.2019, 15:08 Лысков Игорь Витальевич (Старший модератор)

=====
"Если вы заметили, что вы на стороне большинства, —
это верный признак того, что пора меняться." Марк Твен

MarkKnopfler
Посетитель

ID: 403112

# 12

= общий = | 12.06.2019, 15:24 | цитировать цитировать  | профиль профиль  |  отправить письмо в личную почту пейджер
Лысков Игорь Витальевич:


Спасибо, исправим! smile
А вот насчёт "некорректных даты и времени": в таком случае по программе идут команды stc и ret, без сообщения. Или я чего-то не понимаю? smile

Лысков Игорь Витальевич
Старший модератор

ID: 7438

# 13

= общий = | 12.06.2019, 17:27 | цитировать цитировать  | профиль профиль  |  отправить письмо в личную почту пейджер
MarkKnopfler:

А после вызова подпрограммы идет проверка флага С smile

=====
"Если вы заметили, что вы на стороне большинства, —
это верный признак того, что пора меняться." Марк Твен

MarkKnopfler
Посетитель

ID: 403112

# 14

= общий = | 13.06.2019, 19:07 | цитировать цитировать  | профиль профиль  |  отправить письмо в личную почту пейджер
Лысков Игорь Витальевич:

Сегодня задали вопрос, который поставил меня в ступор: что такое и для чего предназначен PSP (префикс программного сегмента)? В интернете информация дана в какой-то размытой формулировке, мало что понял. Можете прояснить этот момент, пожалуйста?

Лысков Игорь Витальевич
Старший модератор

ID: 7438

# 15

 +1 
 
= общий = | 13.06.2019, 20:07 | цитировать цитировать  | профиль профиль  |  отправить письмо в личную почту пейджер
MarkKnopfler:

Что именно непонятно? smile
В двух словах:
1) Перед загрузкой программы в первые 100h выделенного сегмента памяти ОС записывает некоторую информацию.
Адрес сегмента его будет в DS и ES. Если программа формата COM, то все будет в одном сегменте и программа будет сразу за PSP.
И, кстати, поэтому начальное смещение у COM обязано быть равным 100h
2) Многие поля PSP устарели, но некоторые используются до сих пор.
Например, по смещению 0 находится код команды int 20h. Что можно использовать, например, если в начале программы отправить в стек 0, затем завершить командой ret.
Более важной информацией, которая находится в PSP, является строка параметров, которая пишется после имени программы. Находится по смещению 80h
Формат, как для команды 0ah. Отсюда ограничение - длина параметров не более 126 байт (плюс в конце код 0dh и первым байтом реальная длина строки)
А! Еще полезной информацией является поле адреса сегмента окружения(где разные там PATH и т.п.) Сегмент окружения создается перед выделением памяти для программы. А его сегмент записывается в поле 2ch. Сейчас уже не сильно актульно, пишутся больше тесты. А раньше использовалось весьма активно.
Там еще есть адреса обработчиков прерываний int 22h, int 23h, int24h, которые тоже практически не используются. Тем более их всегда можно получить при помощи функции 25h

-----
Последнее редактирование 13.06.2019, 20:55 Лысков Игорь Витальевич (Старший модератор)

=====
"Если вы заметили, что вы на стороне большинства, —
это верный признак того, что пора меняться." Марк Твен

MarkKnopfler
Посетитель

ID: 403112

# 16

= общий = | 13.06.2019, 20:35 | цитировать цитировать  | профиль профиль  |  отправить письмо в личную почту пейджер
Лысков Игорь Витальевич:

Спасибо! Прочитал, что область PSP хранится в памяти с нулевого смещения. Стало быть, адрес и смещение это одно и то?

Лысков Игорь Витальевич
Старший модератор

ID: 7438

# 17

= общий = | 13.06.2019, 20:53 | цитировать цитировать  | профиль профиль  |  отправить письмо в личную почту пейджер

© Цитата:
адрес и смещение это одно и то?
Условно можно считать одним и тем же. Нестрого.
Вообще говоря, адрес в ДОСе - это 20 битное значение, которое получается из пары сегмент:смещение.
В пределах одного сегмента можно считать адрес = смещение, а сегмент как бы подразумевается
Все же, лучше использовать термин "смещение" в пределах сегмента, дабы не было путаницы
Я говорил выше "адрес" некорректно smile

=====
"Если вы заметили, что вы на стороне большинства, —
это верный признак того, что пора меняться." Марк Твен

Лысков Игорь Витальевич
Старший модератор

ID: 7438

# 18

= общий = | 13.06.2019, 20:56 | цитировать цитировать  | профиль профиль  |  отправить письмо в личную почту пейджер
MarkKnopfler:

Подправил свой пост... smile

=====
"Если вы заметили, что вы на стороне большинства, —
это верный признак того, что пора меняться." Марк Твен

MarkKnopfler
Посетитель

ID: 403112

# 19

= общий = | 13.06.2019, 21:02 | цитировать цитировать  | профиль профиль  |  отправить письмо в личную почту пейджер
Лысков Игорь Витальевич:

Вот оно что! smile Побудили больше разобраться по данной теме, есть к чему стремиться smile

 

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

Яндекс Rambler's Top100

главная страница | поддержка | задать вопрос

Время генерирования страницы: 0.17504 сек.

© 2001-2019, Портал RFPRO.RU, Россия
Калашников О.А.  |  Гладенюк А.Г.
Версия системы: 7.77 от 31.05.2019
Версия JS: 1.34 | Версия CSS: 3.35