Пятница, 18.07.2025, 02:26 Приветствую Вас Гость

On-line: Книги, учебники, статьи

Главная | Регистрация | Вход | RSS

Глава 5. Управление файлами(4)

III

Приемы работы с двоичными файлами*. Манипуляция внешними файлами36 основывается на нескольких функциях API, главной и наиболее сложной из которых является функция CreateFile.

В связи с ограниченностью объема книги, мы не можем подробно остановиться на свойствах функции CreateFile. Однако замечу, что с помощью этой функции можно не только создавать или открывать файл, но и такие объекты как каналы (PIPE), консоли, устройства жесткого диска (disk device), коммуникационный ресурс и др. Функция различает устройство по структуре имени. К примеру, "C:\config.sys" определяет файл, a "CONOUT$" - буфер вывода текущей консоли.

Сейчас я представлю две простые, но весьма важные программы (Рис. 2.5.3(1) и Рис. 2.5.3(2)). Обе программы выводят содержимое текстового файла37, имя которого указано в командной строке, в текущую консоль. В первом случае мы получаем дескриптор текущей консоли стандартным способом. Во втором случае - открываем консоль как файл и, соответственно, выводим туда информацию, как в файл. Хочу обратить Ваше внимание на роль буфера, в который читается содержимое файла. Поэкспериментируйте с размером буфера, взяв для пробы большой текстовый файл. Интересно, что в указанных программах никак не учитывается структура текстового файла. Для такого ввода-вывода это ни к чему. Ниже мы поговорим и о структуре текстового файла.


36 Имеется в виду файлами, расположенными на внешнем устройстве.

37 Точнее любого файла, но смысл выводить файл на консоль именно таким образом имеется только для текстового файла.

* Кажется, автор имеет ввиду текстовые файлы, а не бинарные, как это следует из дальнейшего повествования :)


;файл FILES1.ASM
.386P
; плоская модель
.MODEL FLAT, stdcall

; константы
STD_OUTPUT_HANDLE equ -11
GENERIC_READ equ 80000000h
GENERIC_WRITE equ 40000000h
GEN = GENERIC_READ or GENERIC_WRITE
SHARE = 0
OPEN_EXISTING equ 3

; прототипы внешних процедур
EXTERN GetStdHandle@4:NEAR
EXTERN WriteConsoleA@20:NEAR
EXTERN ExitProcess@4:NEAR
EXTERN GetCommandLineA@0:NEAR
EXTERN CreateFileA@28:NEAR
EXTERN CloseHandle@4:NEAR
EXTERN ReadFile@20:NEAR

;-------------------------------------------------
; директивы компоновщику для подключения библиотек
includelib c:\masm32\lib\user32.lib
includelib c:\masm32\lib\kernel32.lib
;-------------------------------------------------

; сегмент данных
_DATA SEGMENT DWORD PUBLIC USE32 'DATA'
 HANDL DWORD ?
 HFILE DWORD ?
 BUF DB 100 DUP (0)
 BUFER DB 300 DUP (0)
 NUMB DWORD ?
 NUMW DWORD ?
_DATA ENDS

; сегмент кода
_TEXT SEGMENT DWORD PUBLIC USE32 'CODE'
START:
; получить HANDLE вывода
 PUSH STD_OUTPUT_HANDLE
 CALL GetStdHandle@4
 MOV HANDL,EAX
; получить количество параметров
 CALL NUMPAR
 CMP EAX,1
 JE NO_PAR
;------------------------------
; получить параметр номером EDI
 MOV EDI,2
 LEA EBX, BUF
 CALL GETPAR
; открыть файл
 PUSH 0 ; должен быть равен 0
 PUSH 0 ; атрибут файла (если создаем)
 PUSH OPEN_EXISTING ; как открывать
 PUSH 0 ; указатель на security attr
 PUSH 0 ; режим общего доступа
 PUSH GEN ; режим доступа
 PUSH OFFSET BUF ; имя файла
 CALL CreateFileA@28
 CMP EAX,-1
 JE NO_PAR
 MOV HFILE, EAX
L00:
; прочесть в буфер
 PUSH 0
 PUSH OFFSET NUMB
 PUSH 300
 PUSH OFFSET BUFER
 PUSH HFILE
 CALL ReadFile@20
; вывести содержимое буфера на консоль
 PUSH 0
 PUSH OFFSET NUMW
 PUSH NUMB
 PUSH OFFSET BUFER
 PUSH HANDL
 CALL WriteConsoleA@20
; проверить, не последние ли байты прочитаны
 CMP NUMB, 300
 JE L00
; закрыть файл
 PUSH HFILE
 CALL CloseHandle@4
; конец работы программы
NO_PAR:
 PUSH 0
 CALL ExitProcess@4

; область процедур
; процедура определения количества параметров в строке
; определить количество параметров (->ЕАX)
NUMPAR PROC
 CALL GetCommandLineA@0
 MOV ESI,EAX ; указатель на строку
 XOR ECX,ECX ; счетчик
 MOV EDX,1 ; признак
L1:
 CMP BYTE PTR [ESI],0
 JE L4
 CMP BYTE PTR [ESI],32
 JE L3
 ADD ECX.EDX ; номер параметра
 MOV EDX,0
 JMP L2
L3:
 OR EDX,1
L2:
 INC ESI
 JMP L1
L4:
 MOV EAX, ECX
 RET
NUMPAR ENDP

; получить параметр из командной строки
; EBX - указывает на буфер, куда будет помещен параметр
; в буфер помещается строка с нулем на конце
; EDI - номер параметра
GETPAR PROC
 CALL GetCommandLineA@0
 MOV ESI,EAX ; указатель на строку
 XOR ECX,ECX ; счетчик
 MOV EDX,1 ; признак
L1:
 CMP BYTE PTR [ESI], 0
 JE L4
 CMP BYTE PTR [ESI],32
 JE L3
 ADD ECX,EDX ; номер параметра
 MOV EDX,0
 JMP L2
L3:
 OR EDX,1
L2:
 CMP ECX,EDI
 JNE L5
 MOV AL, BYTE PTR [ESI]
 MOV BYTE PTR [EBX], AL
 INC EBX
L5:
 INC ESI
 JMP L1
L4:
 MOV BYTE PTR [EBX], 0
 RET
GETPAR ENDP
_TEXT ENDS
END START

Рис. 2.5.3(1). Вывод на консоль содержимого текстового файла. Первый способ.

; файл FILES2.ASM
.386P
; плоская модель
.MODEL FLAT, stdcall

; константы
STD_OUTPUT_HANDLE equ -11
GENERIC_READ equ 80000000h
GENERIC_WRITE equ 40000000h
GEN = GENERIC_READ or GENERIC_WRITE
SHARE = 0
OPEN_EXISTING equ 3

; прототипы внешних процедур
EXTERN ExitProcess@4:NEAR
EXTERN GetCommandLineA@0:NEAR
EXTERN CreateFileA@28:NEAR
EXTERN CloseHandle@4:NEAR
EXTERN ReadFile@20:NEAR
EXTERN WriteFile@20:NEAR
;-------------------------------------------------
; директивы компоновщику для подключения библиотек
; includelib c:\masm32\lib\user32.lib
includelib c:\masm32\lib\kernel32.lib
;-------------------------------------------------

; сегмент данных
_DATA SEGMENT DWORD PUBLIC USE32 'DATA'
 HANDL DWORD ?
 HFILE DWORD ?
 BUF DB 100 DUP (0)
 BUFER DB 300 DUP (0)
 NUMB DWORD ?
 NUMW DWORD ?
 NAMEOUT DB "CONOUT$"
_DATA ENDS

; сегмент кода
_TEXT SEGMENT DWORD PUBLIC USE32 'CODE'
START:

; получить HANDLE вывода (консоли) как файла
 PUSH 0
 PUSH 0
 PUSH OPEN_EXISTING
 PUSH 0
 PUSH 0
 PUSH GEN
 PUSH OFFSET NAMEOUT
 CALL CreateFileA@28
 MOV HANDL,EAX
; получить количество параметров
 CALL NUMPAR
 CMP EAX, 1
 JE NO_PAR
;---------------------------------------------
; получить параметр номером EDI
 MOV EDI,2
 LEA EBX,BUF
 CALL GETPAR
; открыть файл
 PUSH 0
 PUSH 0
 PUSH OPEN_EXISTING
 PUSH 0
 PUSH 0
 PUSH GEN
 PUSH OFFSET BUF
 CALL CreateFileA@28
 CMP EAX,-1
 JE NO_PAR
 MOV HFILE,EAX
L00:
; прочесть в буфер
 PUSH 0
 PUSH OFFSET NUMB
 PUSH 300
 PUSH OFFSET BUFER
 PUSH HFILE
 CALL ReadFile@20
; вывести на консоль как в файл
 PUSH 0
 PUSH OFFSET NUMW
 PUSH NUMB
 PUSH OFFSET BUFER
 PUSH HANDL
 CALL WriteFile@20
 CMP NUMB, 300
 JE L00
; закрыть файл
 PUSH HFILE
 CALL CloseHandle@4
; конец работы программы
NO_PAR:
 PUSH 0
 CALL ExitProcess@4

; область процедур
; процедура определения количества параметров в строке
; определить количество параметров (->EAX)
NUMPAR PROC
 CALL GetCommandLineA@0
 MOV ESI,EAX ; указатель на строку
 XOR ECX,ECX ; счетчик
 MOV EDX,1 ; признак
L1:
 CMP BYTE PTR [ESI],0
 JE L4
 CMP BYTE PTR [ESI],32
 JE L3
 ADD ECX,EDX ; номер параметра
 MOV EDX,0
 JMP L2
L3:
 OR EDX,1
L2:
 INC ESI
 JMP L1
L4:
 MOV EAX,ECX
 RET
NUMPAR ENDP

; получить параметр из командной строки
; EBX - указывает на буфер, куда будет помещен параметр
; в буфер помещается строка с нулем на конце
; EDI - номер параметра
GETPAR PROC
 CALL GetCommandLineA@0
 MOV ESI,EAX ; указатель на строку
 XOR ECX,ECX ; счетчик
 MOV EDX,1 ; признак
L1:
 CMP BYTE PTR [ESI],0 
 JE L4
 CMP BYTE PTR [ESI],32
 JE L3
 ADD ECX,EDX ; номер параметра
 MOV EDX,0
 JMP L2
L3:
 OR EDX,1
L2:
 CMP ECX,EDI
 JNE L5
 MOV AL,BYTE PTR [ESI]
 MOV BYTE PTR [EBX], AL
 INC EBX
L5:
 INC ESI
 JMP L1
L4:
 MOV BYTE PTR [EBX], 0
 RET
GETPAR ENDP
_TEXT ENDS
END START




Вход на сайт
Поиск
Календарь
«  Июль 2025  »
ПнВтСрЧтПтСбВс
 123456
78910111213
14151617181920
21222324252627
28293031
Архив записей
Наш опрос
Как Вам удобнее??
Всего ответов: 341
Мини-чат
Друзья сайта
  • Официальный блог
  • Сообщество uCoz
  • FAQ по системе
  • Инструкции для uCoz
  • Статистика

    Онлайн всего: 1
    Гостей: 1
    Пользователей: 0