Data segment
msg db 'Enter symbols:$'
path db 'C:\temp\asm_file.txt',0 ;путь к файлу
Nfound db 'Symbols in file not found :($'
err_msg db 'EPIC FAIL$'
shift db 0ah,0dh,'$' ;смещение
str_buff db 4 dup (?) ;буффер строки сравнения
symbols db 5h,?, 6 dup(?) ;буффер строки,которую будем искать
pos_dec db ?,?,?,?,?,0ah,'$' ;тут будет десятичная позиция строки в файле
pos_hex db 0 ;шестнадцатиричная позиция строки в файле
temp_pos_hex db ? ;временная позиция в хекс,для отката изменений указателя в файле
Hfile dw ? ;хэндл файла
buff db ? ;буффер чтения символов из файла
endf_flag db 0 ;флаг конца файла
err_flag db 0 ;флаг ошибки чтения из файла
check_flag db 0h ;флаг сходства первого и последнего сивола строки со строкой в файле
found_flag db 0 ;флаг найденной строки
data ends
code segment
assume cs:code,ds:data
Translate proc far ;перед вызовом подпрограммы в стек помещается cs:ip что бы вернуться обратно
;-------------------------------------вынимаем некоторые значения из стека
pop cx ;вынимаем ip в cx
pop bp ;извлекаем cs в bp
pop si ;смещение строки в которую запишется десятичная позиция
pop ax ;адрес строки в файле в шестнадцатиричном виде
mov bx,2710h ;bx = 10000
xor dx,dx ;очищяем dx,в нем будет остаток
div bx ;выполняем деление ax на bx
add ax,48 ;доводим число до ascii прибавив к нему 48
mov [si],al ;заносим число в строку вывода
mov ax,dx ;в ax остаток от деления
inc si ;передвигаемся в строке вывода к след позиции
mov bx,3e8h ;bx = 1000
xor dx,dx
div bx
add ax,48
mov [si],al
mov ax,dx
inc si
xor bx,bx
mov bl,64h ;bl = 100
div bl
add al,48
mov [si],al
mov al,ah ;в ah дробная часть от деления,переносим ее в al
xor ah,ah ;очищаем ah,сюда запишется остаток от деления
inc si
mov bl,0ah ;bl = 10
div bl ;делим ax на bl
add al,48 ;al - целая часть числа от деления,доводим до ascii символа
mov [si],al ;заносим его в строку
inc si
mov al,ah ;в ah дробная часть от деления,переносим ее в al
add al,48 ;оставшуюся дробную часть доводим до ascii,дальше делить не нужно
mov [si],al ;заносим символ в строку
push bp ;возврат управлени основной программе (cs)
push cx ;ip
ret
Translate endp
Read proc far ;чтение символов файла
xor ax,ax
mov ah,3fh ;номер функции
mov bx,Hfile ;хэндл файла
mov cx,1h ;кол-во считываемых байт
lea dx,buff ;смещение буффера чтения
int 21h
jc read_err ;ошибка чтения
cmp ax,0 ;конец чтения файла
je end_of_file
ret
end_of_file:
mov endf_flag,1 ;флаг конца файла в 1
ret
read_err:
mov err_flag,1 ;флаг ошибки чтения в 1
ret
Read endp
check proc far ;подпрограмма проверки 1го и последнего символов строки с некоторой строкой в файле
cmp al,[symbols+2] ;сравнение первого символа
jne r ;не равны
xor ax,ax
mov ah,42h ;номер функции
mov bx,Hfile ;хэндл файла
mov cl,[symbols+1] ;в cl количество сдвигов от начала файла,тоесть длина искомой строки
sub cl,2 ;2-за счет того что ранее был вызван read
;позиция должна быть меньше на единицу позиции считываемого символа
add [pos_hex],cl ;в pos_hex - текущий указтель в файле,после чтения или любого изменения я его меняю
xor cx,cx ;в cx 0,потому что в связке CX:DX могут обрабатываться файлы длинее 65536 байт
mov dl,[pos_hex] ;в dl позиция от начала файла
int 21h ;изменение положения указателя в файле
jc some_err ;какая либо ошибка
call read ;чтение последнего символа искомой строки из какой либо строки в файле
add [pos_hex],1 ;после чтения символа изменяем значение переменной хранящей текущую позицю указателя
cmp [err_flag],1 ;read может выстовлять флаг ошибки чтения
je some_err ;ошибка имело место
mov al,[buff] ;в al - считаный символ
xor bx,bx
mov bl,[symbols+1] ;число символов в искомой строке
inc bx ;что бы смещение перескачило через байт количества введенных символов
cmp al,[symbols+bx] ;сравниваются последние символы искомой и считаной с файла строки
jne not_eq1 ;не равны
mov [check_flag],1 ;если равны,то флаг превой проверки устанавливается в 1
r:ret
not_eq1:
xor ax,ax
mov ah,42h ;номер функции
mov bx,Hfile ;хэндл файла
mov cl,[symbols+1] ;в cl количество символов в искомой строке
dec cl ;что бы количество было меньше на 1
sub [pos_hex],cl ;вычесть из текущей позиции указателя cl,что бы потом считывать след символ
xor cx,cx ;позиция может быть равна (cx*65536)+dx,поэтому cx=0
mov dl,[pos_hex] ;устанавливаемая позиция указателя в файле
int 21h
ret
some_err:
mov [err_flag],1 ;флаг какой либо ошибки устанавливается в 1
ret
check endp
sub_check proc far ;если первый и последний символы искомой строки сошлись с какой либо строкой в файле
;то неоходимо проверить каждый символ этих строк на совпадение
xor ax,ax
mov ah,42h ;номер функции
mov bx,Hfile ;хэндл файла
xor cx,cx
mov dl,[temp_pos_hex] ;в dl временная позиция указателя в файле,была введена для упрощения возврата
; к строке в файле,если ее первый и последний символы сошлись с искомой
int 21h
mov cl,[symbols+1] ;количество символов,которые будут считаны из файла,тоесть,длина искомой строки
lea dx,str_buff ;буффер чтения из файла
cycle:
push cx ;cx в стек,что бы при чтении из файла он не вызвал ошибки
xor ax,ax
mov ah,3fh ;номер функции чтения из файла
mov bx,Hfile ;хэндл файла
mov cx,1h ;будет считан один байт
int 21h
inc dx ;смещаемся по буфферу чтения из файла
pop cx ;востанавливаем cx для сохранения цикла
loop cycle
add [temp_pos_hex],1 ;добавляется 1,потому что если строки не сойдутся
;мы уже не сможем своевременно выполнить эту инструкцию в основной части программы
mov al,[temp_pos_hex] ;потому что в одной инструкции нельзя использовать две косвеных адресации
mov [pos_hex],al ;собственно ради этого и была введена переменная temp_pos_hex
;вычисление смещения для возврата изменений,если строка не сойдется,
;могут создать много ошибок,а если строки сойдутся,то это ни на что не повлияет
xor ax,ax
mov ah,42h ;номер функции
mov bx,Hfile ;хэндл файла
xor cx,cx
mov dl,[pos_hex] ;позия указателя от начала файла,al=0
int 21h
call match ;подпрограмма посимвольного сравнения строк
ret
sub_check endp
match proc ;подпрограмма посимвольного сравнения строк
CLD ;не обязательно,сравнение происходит слева на право
xor cx,cx
mov cl,[symbols+1] ;количество символов в строке
lea di,str_buff ;смещение строки из файла
lea si,symbols ;смещение искомой строки
add si,2 ;что бы перепрыгнуть байты макс сиволов ввода и кол-ва фактически введенных символов
repe cmpsb ;сравнивать строки побайтно,до тех пор пока символы равны
jcxz equals ;0 в cx говорит о том что строки полностью равны
mov [check_flag],0 ;иначе надо сбросить флаг сравнения первого и последнего символов
ret
equals:
sub [temp_pos_hex],1 ;уменешение позиции сравниваемой строки в файле,потому что был вызван read
mov [found_flag],1 ;флаг того,что строки эквивалентны
ret
match endp
begin:
mov ax,data
mov ds,ax
mov es,ax ;для использования repe cmpsb,di исползует сегмент es
xor ax,ax
mov ah,09h
lea dx,msg
int 21h ;вывод сообщения о вводе искомой строки
xor ax,ax
mov ah,0Ah
lea dx,symbols
int 21h ;чтение набора символов
xor ax,ax
mov ah,09h
lea dx,shift
int 21h ;вывод смещения каретки
xor ax,ax
mov ah,3dh
lea dx,path
mov al,00h
int 21h ;открытие файла на диске
jc err_scn ;ошибка открытия файла
mov Hfile,ax ;в Hfile хэндл файла
mov cx,0ffffh ;максимальный обрабатываемый фал не более ffffh байт
read_find:
cmp [found_flag],1 ;флаг того,что искомая строка присутствует в файле,выставляет match
je found
cmp [err_flag],1 ;флаг какой либо ошибки,выставляет read либо смещение указателя в файле
je err_scn
push cx ;в стек счетчик цикла
mov cl,[pos_hex]
mov [temp_pos_hex],cl ;в temp_pos_hex текущая позиция указателя в файле,до того как она будет изменена
call read ;чтение символа из файла
cmp [endf_flag],1 ;флаг конца файла,его выставляет read
je not_found
add [pos_hex],1 ;увеличение текущей позиции указателя в файле
xor ax,ax
mov al,[buff] ;в al - текущий считаный символ
call check ;проверка первого и последнего символов искомой строки с какой либо строклй в файле
pop cx ;возврат счетчика цикла
cmp [check_flag],1 ;идентичны ли первый и последний символы искомой строки с какой либо строкой в файле
jne next_read
push cx ;в стек счетчик цикла
call sub_check ;загрузка всей предпологаемой строки из файла в память и дальнейшая ее проверка
pop cx ;возврат счетчика цикла
next_read:loop read_find ;чтение следующего символа из файла
not_found: ;если искомая строка не присутствует в файле
xor ax,ax
mov ah,09h
lea dx,Nfound
int 21h ;вывод сообщения
jmp ext ;переход к функции возврата в ОС
err_scn: ;если была какая либо ошибка
xor ax,ax
mov ah,09h
lea dx,err_msg
int 21h ;вывод сообщения
jmp ext ;переход к функции возврата в ОС
found: ;если искомая строка была найдена в файле
xor ax,ax
mov al,[temp_pos_hex] ;в al номер позиции этой строки
inc ax ;для того что бы вывод позиции начинался с 1 а не с 0
push ax
push offset pos_dec ;смещение строки для вывода десятичной позиции в файле
call Translate ;преобразование шестнадцатиричной позиции в десятиричную
xor ax,ax
mov ah,09h
lea dx,pos_dec
int 21h ;вывод позиции на экран
ext:
mov ax,4c00h ;функция выхода в ОС
int 21h
code ends
end begin |