14.07.2025
| Главная | Поиск | Регистрация | Профиль | Вход | Выход |
Реклама
Реклама
Интересное
Главная » Статьи » Программирование на Ассемблере » Программирование на Ассемблере

Управление файлами

Управление файлами.

 

Сегодня мы рассмотрим написанную ранее программу.
include kernel32.inc
include user32.inc
include def32.inc

.386

.model flat

.data
Стандартные вложения/установки
error db 'Ошибка',0
error1 db 'Файл не задан',0
error2 db 'Заданный файл не существует',0
fileName dd 0
programHandle dd 0
fileHandle dd 0
memoryHandle dd 0
memoryOffset dd 0
SizeRW dd 0

Переменные:
error - эта надпись выдаётся в синем поле MessageBox
error1,2 - сами ошибки
filename - сюда будет занесён offset на имя файла для открытия
*Handle - handle соответствующего объекта будет храниться в соответствующей переменной
memoryOffset - сюда будет занесён offset отображённой памяти
SizeRW - эта переменная нужна для процедур WriteFile/ReadFile, по идее Microsoft - а её проверкой достигается проверка удачности произведённой процедуры, нам же она нужна только для корректной работы функции.

.code
_start:

xor ebx,ebx

push ebx

call GetModuleHandle

mov programHandle,eax

Стандартное начало программы, обнуление ebx и получения Handle процесса.

call GetCommandLine

mov edi,eax

mov al,20h

mov ecx,-1

repne scasb
В этой части программы мы получаем offset на командную строку(КС) процедурой GetCommandLine(вызывается без параметров!). После этого еах, указывающий на КС мы помещаем в edi. При этом нам надо учесть, что первым в КС всегда идёт имя запущенной программы, а потом уже возможные параметры и т.д. Поэтому мы ищем первый пробел(код 20h)в этой строке, для этого мы помещаем в al код пробела (20h), а есх максимальное его значение и производим "сравнение символа пока не равно"(repne scasb), то есть полученный после этого в edi offset указывает на символ после первого пробела в строке, то есть на первый параметр в командной строке после имя запущенной программы.

cmp byte ptr [edi],0

jne File_OK

mov eax,offset error1

jmp program_error

Здесь мы проверяем само наличие какого-либо параметра, то есть если следующий байт в командной строке 0, то параметра нет, если он есть (байт не равен нулю) происходит переход на метку File_OK, если же параметр не найден, то в еах задаётся offset на нужную в данном случае ошибку и управление передаётся на обработчик ошибок программы, program_error

File_OK:

repe scasb

dec edi

Этими двумя действиями мы находим начало первого параметра, они необходимы, если пользователь нажал лишний пробел или два перед параметром

mov esi,edi

mov fileName,edi

Сохраняем offset названия файла в esi для использования и в переменную, специально созданную для этого

push ebx

push FILE_ATTRIBUTE_ARCHIVE

push OPEN_EXISTING

push ebx

push FILE_SHARE_READ

push GENERIC_READ

push esi

call CreateFile

Стандартная процедура открытия файла, так как мы встречаемся с ней впервые, давайте рассмотрим её более подробно, она получает следующие 8 параметров:
- Файл с атрибутами для других процессов, в нашем случае программа быстро совершает все нужные её действия с файлом и закрывает его, поэтому нет нужды задавать здесь какие-либо параметры.
- Атрибуты файла, единственный реально НУЖНЫЙ атрибут, это атрибут архивности файла, выставляем только его.
- Атрибуты создания файла, определяет как открывать файл (создать ли его или открыть в любом случае или только существующий файл), нам нужен существующий файл, поэтому выставляем этот флаг.
- Указатель на структуру атрибутов защиты, пока нам это не нужно, поэтому будет 0.
- Разделяемость файла с другими процессами, в принципе не особо нужно, но чтоб не быть жадиной лучше разрешить другим процессам читать этот файл.
- Доступ, нужный нам, сейчас мы собираемся лишь прочитать его содержимое, то есть ставим "просто чтение".
- Указатель на имя файла, думаю, что комментарии не нужны;)

cmp eax,-1

jne file_opened_OK

mov eax,offset error2

jmp program_error
Проверка на ошибку.
file_opened_OK:

mov fileHandle,eax

push ebx

push eax

call GetFileSize

Сохраняем handle открытого файла и получаем его размер(естественно в еах).

mov edi,eax

push eax

push GMEM_MOVEABLE or GMEM_ZEROINIT

call GlobalAlloc

В начале сохраняем размер файла в edi, так как нам понадобится использовать его достаточно часто. После этого создаём объект памяти, способный вместить в себя весь файл.

mov memoryHandle,eax

push eax

call GlobalLock

mov memoryOffset,eax

Сохраняем его Handle и отображаем в память. После чего сохраняем и offset отображённой памяти.

push ebx

push offset SizeRW

push edi

push eax

push fileHandle

call ReadFile

push fileHandle

call CloseHandle

call CheckSymbol

В этом куске программы мы считываем весь файл в созданную память и закрываем файл. После чего передаём управление нашей процедуре, которая заменяет все "s" на "$" в памяти.

push ebx

push FILE_ATTRIBUTE_ARCHIVE

push TRUNCATE_EXISTING

push ebx

push FILE_SHARE_WRITE

push GENERIC_WRITE

push fileName

call CreateFile

Пересоздаём файл, заданный в командной строке, мы открываем его и удаляем из него всё (в Паскале это можно записать как rewrite(x)).

push ebx

push offset SizeRW

push edi

push memoryOffset

push FileHandle

call WriteFile

push fileHandle

call CloseHandle

Теперь мы записываем прокорректированное содержание в файл и закрываем его.

program_end:

push memoryOffset

call GlobalUnlock

push memoryHandle

call GlobalFree

push ebx

call exitProcess

Это конец программы, здесь мы просто закрываем все используемые нами объекты и завершаем программу.

program_error:

push MB_IconWarning

push offset error

push eax

push ebx

call MessageBox

jmp program_end

На этот кусок кода передаётся управление если произошла ошибка, тогда просто выводится сообщение об ошибке и передаётся управление на завершение программы.

CheckSymbol
proc

push edi

mov al,'s'

mov ecx,edi

inc ecx

mov edi,memoryOffset

В начале процедуры мы подготавливаем регистры, здесь стоит заметить, что перед вызовом процедуры мы сохранили размер файла, что равно размеру сохранённого в памяти, в edi. Мы помещаем это значение в регистр счётчика (есх), в al символ, который мы хотим заменить, а в edi offset на память с содержимым файла.

loop_check:

repne scasb

test ecx,ecx

jz end_check

mov byte ptr [edi-1],'$'

jmp loop_check
end_check:

Это главная часть программы, так называемое ядро программы, так как эти 7 строчек выполняю нужную работу, а всё остальное лишь собирает информацию и передаёт её этой процедуре. Работа нашего "ядра" происходит по следующему сценарию, программы проверяет символ за символом на наличие заданного символа до тех пор, пока либо не будет найден символ, либо не кончится источник, если источник кончился управление передаётся на метку end_check, то есть происходит завершение цикла, если же найден символ, то он заменяется на новый и цикл продолжается.

pop edi

ret
CheckSymbol endp

end _start
Категория: Программирование на Ассемблере | Добавил: MalCer (25.09.2009)
Просмотров: 707 | Рейтинг: 0.0/0 |
Всего комментариев: 0
Реклама
Кабинет

Читать ЛС ()

Гость, мы рады вас видеть. Пожалуйста зарегистрируйтесь или авторизуйтесь!



Фраза дня:
Кто с нами

Сегодня были:
Статистика
Партнеры
Graffiti Decorations(R) Studio (TM) Site Promoter Mnogo-softa.net.ru-Софт,срипты,шаблоны и др. MEGA-ToP-ТОП раскрутка раскрутка сайтов. Рейтинг лучших сайтов
описание