Министерство Высшего образования РФ
ИжГТУ
Кафедра ВТ
Отчёт по лабораторным работам по курсу СПО.
Выполнил: студент 862 гр.
Мымрин В.Г.
Проверил: Вахрушева Е. А.
Ижевск
2001 г.
Лабораторная работа №1
Задание: найти подкаталоги, имеющие лишние кластеры (оставленные после удаления файлов) и указать потери дискового пространства.
Разработка алгоритма: структура каталогов файловой системы FAT представлена в виде древовидной структуры. Т.е. каждый каталог является файлом, в котором записана информация о входящем в него файлах и каталогах.
Информация в каталоге хранится в виде 32-разрядных записей (дескрипторов),
Алгоритм выполнения программы выглядит следующим образом: просматривается вначале корневой каталог на наличие в нем каталогов, если такой каталог имеется, то выполняется переход к нему. Если в данном каталоге имеются удаленные файлы, то выполняется расчет размера файла в кластерах. После просмотра всего каталога выполняется переход к вышестоящему (родительскому) каталогу, выводится на экран название только что проверенного каталога и размер (в кластерах) занимаемыми удаленными файлами. Поиск заканчивается, когда будет просканирован весь корневой каталог.
Листинг программы:
.model small
.stack 100h
.data
BufferLen equ 1024 ;Длина буфера в байтах
Buffer DB BufferLen dup (0) ;Буфер для чтения секторов
AfterFAT dw ? ;Количество секторов занимаемых FAT и корневым
;каталогом
Clusters dw ? ;количество кластеров на диске
SecFAT dw ? ;Номер сектора области данных
Counter dw ? ;Счетчик
Sectors dw ? ;Количество секторов в кластере
Number dw ?
Rec dw 6 dup (0) ;Структура для чтения сектора
SecCounter dw ? ;Счетчик секторов
OffsCounter dw ? ;Смещение в буфере
RootSize dw ? ;Размер корневого каталога в секторах
clDir dw ? ;Номер первого сектора каждого кластера
FileSize dw ? ;Размер файлов в кластерах
NameDir db 15 dup ('$') ;Название каталога
Disk db 0 ;Номер читаемого диска
.code
;П/П для чтения сектора в заданном кластере
ReadCluster proc nCluster, nSector
mov bp,sp
sub bp,2
mov dx,nCluster ;Номер кластера
sub dx,2
mov ax,Sectors ;Умножается на кол-во секторов в кластере
mul dx
add ax,nSector ;Добавляется смещение
adc dx,0
add ax,AfterFAT ;Добавляется длина FAT
adc dx,0
add ax,RootSize ;Добавляется длина корневого каталога
adc dx,0
mov Rec,ax ;Начальный номер сектора
mov Rec+2,dx
mov Rec+4,BufferLen/512 ;Количество секторов для чтения
mov cx,0FFFFh ;Признак
lea bx,Buffer ;Указатель на буфер данных
mov Rec+8,ds
mov Rec+6,bx
lea bx,Rec
mov al,Disk ;N накопителя
int 25h ;Чтение сектора
pop cx ;Восстановление сектора
ret
endp
;подпрограмма для перевода курсора на следующую строку
LineFeed proc n
push bx ;сохранение регистров в стеке
push ax
push dx
mov ax,0601h ;Прокрутить на одну строку вверх
mov bh,07 ;Атрибут: нормальный, черно-белый
mov cx,0000 ;Координаты от 00,00
mov dx,184Fh ; до 24,79 (полный экран)
int 10h ;Вызвать BIOS
mov bh,0
mov ax,0300h ;выбор функции прерывания - чтение позиции курсора
int 10h ;вызов прерывания
mov dl,0 ;добавление к существующим координатам смещение
mov ah,2 ;выбор функции прерывания - установка
;позиции курсора
int 10h ;вызов прерывания
pop dx ;восстановление регистров
pop ax
pop bx
ret
LineFeed endp
;подпрограмма для перевода числа в символьное представление
IntToStr proc near
push ax ;сохранение регистров в стеке
push dx
push bx
push cx
mov ax,number ;чтение переданного числа
cmp ax,0 ;сравнение с нулем
jz ShowChar ;если нуль,то...
mov bx,10 ;подготовка в делению
mov cx,ax ;запись числа
mov ax,10000 ;задание начального размера делителя
cmp ax,Number
jb cont_1
Cont_m:
mov dx,0
div bx ;разделить делитель на 10
cmp ax,cx ;сравнить с числом
jg cont_m ;если делитель больше числа, то продолжить
;цикл деления
cont_1:
mov bx,ax ;запись делителя
mov ax,cx
cmp bx,1 ;сравнение делителя с 1
jz ShowChar ;если равен 1, то переход на метку
mov ax,cx ;иначе восстановление прежнего числа
;цикл деления числа и извлечение из него частного
cont_d: mov dx,0
div bx ;деление числа на делитель
push ax ;сохранение регистров в стеке
push dx
mov dx,0
mov ax,bx ;запись делителя в регистр
mov bx,10
div bx ;деление делителя на 10
mov bx,ax ;запись нового делителя
pop dx
pop ax ;восстановление регистров из стека
push dx
mov dl,al ;в dl частное
add dl,30h ;теперь код символа
mov ah,6
int 21h ;вывод символа на экран
pop dx
mov ax,dx ;запись остатка от деления
cmp bx,1
jg cont_d ;цикл продолжается, пока от делителя
;не останется 1
ShowChar:mov dl,al ;запись в регистр числа
add dl,30h ;преобразование в код
mov ah,6 ;выбор функции прерывания - вывод
;символа на экран
int 21h ;вызов прерывания
pop cx ;восстановление регистров
pop bx
pop dx
pop ax
ret
IntToStr endp
.startup
mov Disk,2 ;Задание номера диска
mov Number,0
mov ah,1ch
mov dx,Disk
inc dx
mov cx,0
int 21h ;Вызов прерывания для получения
;информации накопителя
xor ah,ah
mov Sectors,ax ;Кол-во секторов в кластере
mov Clusters,dx ;Кол-во кластеров в разделе
sub Clusters,2
;Чтение MBR
lea bx,Buffer ;Буфер данных
mov dx,0 ;Логический номер сектора
mov cx,1 ;Читать 1 сектор
mov al,Disk ;N накопителя
int 25h ;Чтение сектора
pop cx ;Восстановление стека
mov ax,[bx+22] ;в AX длина FAT в секторах
mov AfterFAT,ax
add AfterFAT,ax
inc AfterFAT ;Добавление длины MBR
mov ax,[bx+17]
shr ax,4
mov RootSize,ax ;Длина корневого каталога
mov ax,AfterFAT ;Чтение номера сектора начала данных
mov OffsCounter,0
mov SecCounter,0
mov SecFAT,ax ;Чтение FAT
lea bx,Buffer ;Буфер данных
mov dx,SecFAT ;Логический номер сектора
mov cx,BufferLen/512 ;Кол-во секторов для чтения
mov al,Disk ;N накопителя
int 25h ;Чтение сектора
pop CX ;Восстановление стека
mov FileSize,0
dirCycle:
mov bx,OffsCounter
mov al,[bx+11] ;Чтение атрибута файла из дескриптора
cmp al,15 ;Проверка, не является ли VFAT
jz Pass
test al,16
jz CheckName ;Если это не каталог, то переход на метку
mov al,[bx]
cmp al,0e5h ;Проверка, является ли каталог удаленным
jz pass ;Переход, если это так
mov dx,[bx+26] ;Чтение начального номера кластера файла
mov clDir,dx
push OffsCounter ;Запоминание параметров данного каталога
push SecCounter
push FileSize
push SecCounter dx
call ReadCluster ;Вызов процедуры чтения сектора
pop dx ax
mov OffsCounter,64 ;Указатель на третий элемент дескриптора
mov SecCounter,0
mov FileSize,0
NeXT: jmp dirCycle
jmpDir:
jmp dirCycle
CheckName:
mov al,[bx]
cmp al,0E5H ;Проверка, является ли файл удаленным
jnz Pass
mov cx,Sectors ;Этот файл удален. Подсчитывается его
shl cx,9 ;длина в кластерах
mov dx,[bx+30]
cmp dx,0ffffh
jz pass
mov ax,[bx+28]
div cx
pop FileSize
add FileSize,ax
inc FileSize
push FileSize
Pass: add OffsCounter,32 ;Переход к следующему элементу дискриптора
cmp OffsCounter,BufferLen;Проверка на выход за границы буфера
jnz jmpDir ;Внутрений цикл - сканирование буфера
add SecCounter,BufferLen/512
push SecCounter clDir
call ReadCluster ;Чтение следующего сектора кластера с каталогом
pop dx ax
mov OffsCounter,0
mov ax,SecCounter
cmp ax,Sectors
jnz jmpDir ;Внешний цикл - сканирование кластера
cmp clDir,0 ;Если проверен последний сектор
;корневого каталога
jz toEnd ;то на выход
;Цикл просмотра кластера закончен
mov ax,0 ;Чтение первого сектора каталога
push ax clDir
call ReadCluster
pop clDir ax
pop FileSize
pop SecCounter
pop OffsCounter
lea bx,Buffer
mov dx,[bx+58] ;Номер сектора родительского каталога
mov clDir,dx
cmp clDir,0 ;Чтение родительского каталога
jz ReadRoot
mov ax,SecCounter
push ax dx
call ReadCluster
pop dx ax
jmp m1 ;Переход на метку вывода имени
;каталога на экран
toEnd: jmp EndPr
ReadRoot: ;Чтение корневого каталога
mov dx,AfterFAT
add dx,SecCounter
lea bx,Buffer ;Буфер данных
mov cx,BufferLen/512 ;Кол-во секторов для чтения
mov al,Disk ;N накопителя
int 25h ;Чтение сектора
pop cx ;Восстановление стека
jmp m1
NeXT1:jmp NeXT
m1: mov bx,OffsCounter
mov al,[bx] ;А если это каталог. то вывод его имени
;на экран
cmp al,0E5H
jz Cont
mov si,0
Copy: mov al,[bx+si]
mov NameDir+si,al
inc si
cmp si,8
jnz Copy ;Цикл копирования имени каталога в строку
mov [NameDir+8],36
lea dx, NameDir
mov ah,9
int 21h ;Вывод строки с именем каталога на экран
mov bh,0
mov ax,0300h ;выбор функции прерывания - чтение позиции
;курсора
int 10h ;вызов прерывания
add dl,4 ;добавление к существующим координатам смещение
mov ah,2 ;выбор функции прерывания - установка
;позиции курсора
int 10h ;вызов прерывания
mov ax,FileSize
mov FileSize,0
mov Number,ax
call IntToStr ;Вывод на экран кол-ва кластеров занимаемых
call LineFeed ;удаленным файлами
mov ah,6
mov dl,13
int 21h
Cont:
add OffsCounter,32 ;Переход на следующий дескриптор
mov ax,OffsCounter
cmp OffsCounter,BufferLen;Проверка на выход за границы буфера
jnz NeXT1
add SecCounter,BufferLen/512;Чтение следующего сектора кластера
;с каталогом
mov OffsCounter,0
cmp clDir,0 ;Сравнение номера кластера
jnz Cont1
mov dx,AfterFAT ;Чтение сектора корневого каталога
add dx,SecCounter
lea bx,Buffer ;указываем на буфер данных
mov cx,BufferLen/512 ;2 сектора
mov al,2 ;накопитель C
int 25h ;читаем сектора
pop cx ;восстанавливаем стек
jmp Pass1
Cont1:push SecCounter clDir ;Чтение сектора
call ReadCluster
pop dx ax
Pass1:mov ax,SecCounter
cmp ax,Sectors
jz EndPr ;Внешний цикл - сканирование кластера
EndPr:jmp NeXT1
.exit
end
Лабораторная работа №2
Задание: среди "свободных" кластеров найти кластеры, содержащие текстовую информацию (текст-латиница) и вывести их с указанием номеров.
Разработка алгоритма: анализируется таблица FAT. Если в ней встречаются элементы, содержащие нули, то осуществляется чтение данного кластера. Затем, выполняется подсчет латинских символов. Если их количество больше половины длины кластера, то на экран выводится номер кластера.
Листинг программы:
.model small
.stack 100h
.data
BufferLen equ 1024
Buffer DB BufferLen dup (0) ;отводим место для 2 секторов
AfterFAT dw ?
Clusters dw ? ;количество кластеров на диске
SecFAT dw ? ;Номер сектора области данных
ClCounter dw ? ;Счетчик кластеров
Counter dw ? ;Счетчик
Sectors dw ? ;Количество секторов в кластере
Number dw ?
Rec dw 6 dup (0)
SecCounter dw ?
OffsCounter dw ?
CBuffer db BufferLen dup (0) ;Буфер для чтения содержимого сектора
.code
;подпрограмма для перевода числа в символьное представление
IntToStr proc near
push ax ;сохранение регистров в стеке
push dx
push bx
push cx
mov ax,number ;чтение переданного числа
cmp ax,0 ;сравнение с нулем
jz ShowChar ;если нуль,то...
mov bx,10 ;подготовка в делению
mov cx,ax ;запись числа
mov ax,10000 ;задание начального размера делителя
cmp ax,Number
jb cont1
Cont_m:mov dx,0
div bx ;разделить делитель на 10
cmp ax,cx ;сравнить с числом
jg cont_m ;если делитель больше числа, то
;продолжить цикл деления
cont1:mov bx,ax ;запись делителя
mov ax,cx
cmp bx,1 ;сравнение делителя с 1
jz ShowChar ;если равен 1, то переход на метку
mov ax,cx ;иначе восстановление прежнего числа
;цикл деления числа и извлечение из
;него частного
cont_d: mov dx,0
div bx ;деление числа на делитель
push ax ;сохранение регистров в стеке
push dx
mov dx,0
mov ax,bx ;запись делителя в регистр
mov bx,10
div bx ;деление делителя на 10
mov bx,ax ;запись нового делителя
pop dx
pop ax ;восстановление регистров из стека
push dx
mov dl,al ;в dl частное
add dl,30h ;теперь код символа
mov ah,6
int 21h ;вывод символа на экран
pop dx
mov ax,dx ;запись остатка от деления
cmp bx,1
jg cont_d ;цикл продолжается, пока от делителя
;не останется 1
ShowChar:mov dl,al ;запись в регистр числа
add dl,30h ;преобразование в код
mov ah,6 ;выбор функции прерывания - вывод символа
;на экран
int 21h ;вызов прерывания
pop cx ;восстановление регистров
pop bx
pop dx
pop ax
ret
IntToStr endp
.startup
mov Number,0
mov ah,1ch
mov dx,3
mov cx,0
int 21h ;Вызов прерывания для получения информации
;накопителя
xor ah,ah
mov Sectors,ax ;Кол-во секторов в кластере
mov Clusters,dx ;Кол-во кластеров в разделе
sub Clusters,2
;Чтение MBR
lea bx,Buffer ;Буфер данных
mov dx,0 ;Логический номер сектора
mov cx,1 ;Читать 1 сектор
mov al,2 ;N накопителя
int 25h ;Чтение сектора
pop cx ;Восстановление стека
mov ax,[bx+22] ;в AX длина FAT к секторах
mov AfterFAT,ax
add AfterFAT,ax
inc AfterFAT
mov ax,[bx+17] ;в АХ длина корневого каталога
shr ax,4
add AfterFAT,ax
mov ax,AfterFAT
mov SecFAT,1 ;Чтение FAT
lea bx,Buffer ;Буфер данных
mov dx,SecFAT ;Логический номер сектора
mov cx,2 ;2 сектора
mov al,2 ;накопитель C
int 25h ;Чтение сектора
pop cx ;Восстановление стека
mov cx,Clusters ;счетчик цикла
mov Counter,cx
mov ClCounter,0 ;счетчик номера кластера
mov OffsCounter,2
cycle:mov ax,OffsCounter
cmp ax,BufferLen+2 ;Проверка на выход за границы буфера
jnz NoRead
;Чтение следуюшего сектора FAT
lea bx,Buffer ;Буфер данных
mov ax,BufferLen/512
add SecFAT,ax
mov dx,SecFAT ;Логический номер сектора
mov cx,ax
mov al,2 ;накопитель C
int 25h ;Чтение сектора
pop cx ;Восстановление стека
mov OffsCounter,0
NoRead:mov bx,OffsCounter
mov dx,word ptr [bx] ;получаем 2 байта из таблицы FAT
cmp dx,0
jz RdSec ;если кластер пустой
jmp Cont
rdSec: ;Чтение "пустого" сектора
mov dx,ClCounter ;логический номер сектора
sub dx,2
mov ax,Sectors
mul dx
add ax,AfterFAT ;Вычисление номера сектора
mov si,Sectors
mov SecCounter,si
jmp toNeXT1
NeXT: jmp Cycle
toNeXT1:
mov Rec,ax
mov Rec+2,dx
mov Rec+4,BufferLen/512
rdCycle:mov cx,0FFFFh
lea bx,CBuffer ;указываем на буфер данных
mov Rec+8,ds
mov Rec+6,bx
lea bx,Rec
mov al,2 ;накопитель C
int 25h ;читаем сектора
pop cx ;восстанавливаем стек
mov cx,BufferLen
lea bx,CBuffer
mov si,0
mov dx,0
scCycle: ;Цикл просмотра буфера, поиск текста от A до z
mov al,[bx+si]
inc si
cmp al,65 ;Сравнение c кодом символа А
jb scCont
cmp al,122 ;Сравнение c кодом символа z
ja scCont
inc dx ;Счетчик латинских букв
scCont:loop scCycle
cmp dx,BufferLen/2
jb Cont ;Переход если счетчик латинских символов
;будет меньше половины длины буфера
mov ax,ClCounter ;Счетчик номера кластера
cmp Number,ax
jz Pass
mov Number,ax
call IntToStr ;Вывод номера кластера на экран
mov dl,32 ;теперь код пробела
mov ah,6
int 21h ;вывод символа на экран
Pass: add Rec,BufferLen/512 ;Переход к следующему элементу FAT
jno toNeXT
inc Rec+2
toNext:sub SecCounter,BufferLen/512;Переход к следующему сектору FAT
jnz rdCycle
Cont: add OffsCounter,2
inc ClCounter
dec Counter ;Выход из цикла по обнулении счетчика Counter
jz ToEnd
jmp NeXT
ToEnd:
.exit
end
Лабораторная работа №3
Задание: Написать программу выделения дискового пространства под файл
указанного размера и без фрагментациеи .
{ Написать программу выделения дискового пространства под файл
указанного размера с без фрагментациеи . }
program videlenie;
uses crt; {Будем использовать функции модуля CRT}
var i,j:word; {ПОН}
buff : array [1..4608] of byte; {Буффер для работы с диском}
kor_sec,nach_dan,clustsiz:word; {Для сохранения двнных 0-ого кластера}
Fat : array [1..3072] of word; {Таблица FAT (16)}
nach_klast :word; {Номер кластера начала файла}
dir,Exitp : boolean; {Признак каталога,наличия места на диске}
noklasteraoglav : word; {Номер кластера оглавления}
v : longint; {Размер файла [байт]}
c : integer; {Результат преобразования строки в число}
razm : word; {Размер файла в кластерах}
nachklast : word; {Номер кластера с которого можно начать размещение}
s: string; {Имя файла}
procedure elem_ogl(i:word); {Читает i-ый элемент оглавления }
var claster,j : word; { кластера noklasteraoglav и возвращает}
begin { начальный кластер данных и }
claster :=noklasteraoglav+i div 16;{ рпизнак каталога }
i:=i mod 16;
asm
mov ax,0 { Каждый элемент оглавления имеет}
mov dx,claster { длину 32 байта ($20)}
mov cx,1
mov bx,offset buff;
int 25h
pop dx
end;
clrscr;
nach_klast :=buff[$20*i+27]+buff[$20*i+28]*256;
if (buff [$20*i+12] and $10 <> 0) then dir := true
else dir := false;
end;
function path(s:string):string; {Процедура дополняет имя файла пробелами }
var s1,s2 : string;
tochka : boolean; {Признак расширения}
k,i:byte;
begin
s1:=' '; {Заготовка имени файла}
s2:=''; {Расширение файла}
tochka:=false;
i:=1;
while i <= byte(s[0]) do {Пока не конец имени файла}
begin
begin
if (s[i] = '.') then { Если нашли точку, то}
begin
tochka := true; {устанавливаем признак расширения}
end
else
begin
if not(tochka) then {Если обрабатывается имя, то}
begin
if (s[i] >= 'a') and(s[i] <= 'z') then {Преобразовываем}
s1[i] := char(byte(s[i]) and 223) {маленькие буквы в большие}
else { и записываем в S1}
s1[i] := char(byte(s[i]));
end
else
begin {Если обрабатываем расширение, то}
while (s[i] <> '\') and (i <= byte(s[0])) do {Считываем}
begin {расширение в S2}
s2:=s2+s[i];
inc(i);
end;
if s2 <> '' then {Если расширение есть, то}
begin
for k:=1 to length(s2) do
begin {Преобразование в большие буквы и запись в S1 c конца}
if (s2[length(s2)-k+1] >= 'a') and(s2[length(s2)-k+1] <= 'z') then
s1[12-k] := chr(byte(s2[length(s2)-k+1]) and 223)
else
s1[12-k] := s2[length(s2)-k+1];
end;
end;
end;
end;
end;
i:=i+1; { Переход к след.символу имени}
end;
path := s1; {Возвращаем имя файла}
end;
begin
clrscr;
asm { Читаем нулевой кластер }
mov ax,0 { Диск A }
mov dx,0 { 0-ой кластер }
mov cx,1 { 1 кластер }
mov bx,offset buff;
int 25h
pop dx
end;
kor_sec:=((buff[18]+buff[19]*256)*32)div(buff[12]+buff[13]*256);{Корневых секторов}
nach_dan:=buff[15]+buff[16]*256+kor_sec+(buff[23]+buff[24]*256)*buff[17];{Начало данных}
clustsiz:=buff[14]; {Секторов на единицу размещения}
noklasteraoglav := (buff[23]+buff[24]*256)*buff[17]+buff[15]+buff[16]*256;{Номер кластера оголавления}
asm
mov ax,0 {Читаем FAT}
mov dx,1
mov cx,9
mov bx,offset buff;
int 25h
pop dx
end;
j:=1;
i:=1;
repeat {Преобразование FAT12 - FAT16}
fat[j]:=((buff[i]+buff[i+1]*256)) and 4095; {Записываем 1-12 биты}
fat[j+1]:=((buff[i+1] + buff[i+2]*256 )shr 4) and 4095 ;{13-24 биты}
i:=i+3; {Переход к следующей тойке FAT12}
j:=j+2; {Переход к следующей паре FAT16}
until(i>=(4608-3));
if paramcount = 2 then{Если есть 2 параметра,то начинаем обработку}
begin
razm := 0; {Обнуляем размер}
val (paramstr(2),v,c); { Пребразование 2-ого параметра в число}
if c = 0 then {Если преобразование прошло успешно, то}
begin
razm:=v div 512 ; {Определяем размер файла}
if v mod 512 <> 0 then inc(razm); { в кластерах }
i :=0;
j :=0;
Exitp:=false;
repeat {Просмотр FAT}
inc(i); {Переход к след. элементу FAT}
if fat[i] = 0 then {Если свободен, то}
begin
j:=j+1; {наращиваем счетчик свободных кластеров}
if j = razm then Exitp := true; {Если нашли необходимое число }
end {кластеров, то прекращаем поиск }
else
begin {Если кластер занят то}
j:=0; {обнуляем сч-к свободных кластеров}
nachklast:= i;{и предполагаем что со следующего кластера начнется}
end; {свободные кластеры }
until(i>=3072) or (Exitp); {Пока не пройдем по всем элементам массива}
if Exitp then {Если нашли место, то}
begin
i:=0;
elem_ogl(i); {Считываем первый элемент оглавления}
{Ищем сободный элемент оглавления}
while (buff[$20*i+1] <> 0) and (buff[$20*i+1] <> byte('х'))and(noklasteraoglav < nach_dan) do
begin
if noklasteraoglav < nach_dan then {Если в корневом оглавлении}
begin { то }
i:=i+1; {Переходим к следующему элементу}
if (i = 16) then {Если следующий элемент в другом }
begin {кластере то}
inc(noklasteraoglav); {увеличиваем кластер оглавления}
i:=0;
end;
elem_ogl(i); {Считываем следующий элемет оглавления}
end;
end;
if noklasteraoglav < nach_dan then {Если нашли свободный элемент}
begin {то}
j:=0;
s:= paramstr(1); {преобразуем имя файла}
s:= path (s);
repeat
j:=j+1;
buff[$20*i+j] := byte(s[j]); {Записываем имя файла}
until(j = 11);
buff[$20*i+12] := 0; {Атрибут}
buff[$20*i+23] := 0; {Время}
buff[$20*i+24] := 0; { создания}
buff[$20*i+25] := 0; {Дата}
buff[$20*i+26] := 0; { создания}
