Программа должна открыть текстовый файл и найти все строки, начинающиеся на символ 1 Код Ставлю указатель на начало invoke SetFilePointer, FileHandle,0,0,FILE_BEGIN Дальше заношу первый символ в буфер invoke ReadFile, fHandle, ADDR buf, 1, ADDR cRead, 0 Далее сравниваю mov eax,1 cmp eax, buf jne ПЕРЕХОД_НА_НОВУЮ_СТРОКУ Как этот переход на новую строку сделать элегантным и красивым, уважаемые мастера оптимизации? У меня очень уж грубо... cmp eax, buf jne NEWSTROKA proc invoke SetFilePointer, fHandle, 13, 0, FILE_BEGIN invoke SetFilePointer, fHandle, 10, 0, FILE_BEGIN ret NEWSTROKA endp И второй вопрос, если можно - как покрасивее узнать, что просмотрена последняя строка в текстовом файле, и можно выходить? Своё показывать боюсь - это "нечто" из 18 строк, где опять используется моя "знаменитая" процедура NEWSTROKA ... Правда всё это работает... Помогите новичку, плиз.
invoke SetFilePointer, fHandle, 13, 0, FILE_BEGIN invoke SetFilePointer, fHandle, 10, 0, FILE_BEGIN вотэто янипонял. ты сначала переносишь себя на 13й символ, потом 10й.. то ли я так туплю сёдня тооли лыжи задом на перёд одел.. вобще почему не сделать маппинг(CreateFileMapping+MapViewOfFile) и не сканить буффер вдоль?
А вот это даже странно как-то те SetFilePointer если подразумеваются для перехода на символ после 10,13, то неправильно. Если на то пошло, нужно побайтово считывать файл и искать там 13 и следующую за ним 10. Тогда мы и попадем на новую строку. насчет красивости перехода. если имеется в виду аскии символ 1, а не байт со значением 1, то нужно вместо 1 писать '1' и buf должно быть инициализировано DWORD (0) перед вызовом ReadFile, если это локальная переменная. Ну и сам переход красивее не сделаешь Конец файла находится по значению cRead, которая показывает, сколько байт считано. Если ноль, значит файл кончился короче, если совсем уж новичок, сначала продумай алгоритм, по которому ищутся строки, начинающиеся на 1 и как они должны быть представлены на выходе вот как то вот так вот
а естчо лучше - представь фаел как строку 'abcdefg',13,10,'hijkl'.. асм это весьма наглядно показал.. хотя тут пациенту надо и аски учить, и "двухмерные массивы", и логику слушать - что самое сложное.. это и есть та единственная ситуация, когда я считаю, что лучше бы чел начал с делфи или другога ООЯП. =\ вот так то как то так вот.
TOLSTOPUZ Код (Text): cmp buf,'1' ; 7 байт jne new_str_label ; 2 байта, если метка в бинарном диаметре не больше 128 У тебя получается Код (Text): >mov eax,'1' ; 5 байт - неправильно, сравниваем байты, правильно дальше mov al,'1' ; 2 байта >cmp eax, buf ; 3 байта - но здесь неправильно, т.к. ты считал байт, а сравниваешь DWORD'ы > ; правильно дальше cmp al,[buf] ; 6 байт jne new_str_label ; 2 байта, если метка в бинарном диаметре не больше 128 В твоем случае читаешь по-байтно, и сравниваешь два смежных байта с 0Dh,0Ah, плюс следишь за тем, когда кончится файл. Но это действительно неэффективно. Если еще не изучи проецирование файлов (File Mapping), то изучи, и тогда будешь читать файл как память - намного более просто получится и более эффективно в плане скорости, т.к. прочитанный буфер кешируется. Конец файла узнаешь по его размеру (GetFileSize(hFile,0)), новую строку узнаешь сравнением (cmp word ptr file_data,0A0Dh). Когда будешь открывать файл используй флаг FILE_FLAG_SEQUENTIAL_SCAN функции CreateFile, это оптимизирует операции кеширования, учитывая то, что ты будешь читать файл строго последовательно. Однако, если отступить от этого правила будут провалы производительности.
TOLSTOPUZ Очень сложно объяснили. SetFilePointer не найдет конца строки. Найди Си-шную фуннкцию, которая это делает - читает строки. Либо тупо ищи символы 13,10. А вот за ними как раз надо искать '1'. А про Filemapping - это как в той рекламе - рано еще такому молодому, УВЫ.
да бред! чо вы поцана портите? ниуя не рано, если у него "воин зена" написано под ником! пусть учится без поблажек, ато ёпт хекеры скоро вымрут нахрен все =\\ тем более mapping. это не такая уж сложная функция. парень на асме пишет, а ты сишную функцию.. правильно Osen говорит: пусть ищет WORD 0A0Dh (в памяти и на диске эта цифра будет как раз 0D0Ah).. /* и НЕ правильно говорит Osen - не 1013h, ибо это байты 19 и 16, не путай мальчика .) */ ..то есть найдя последовательность 0d,0a ты прибавляешь 2 к указателю (то есть с переноса на строку переходишь к самой строке) и сравниваешь первый символ с 31м символом, или просто с '1'. изучи маппинг.
Прошу прощения, Вы говорите надо искать структуру WORD 0A0Dh То есть не нужно значит сначала 13, потом 10 а сразу 0ADh ? Тогда это значит не побайтно, а "пословно", так сказать. Но передвигаться по памяти все равно нужно побайтно? Т.е. можно это прикинуть примерно вот так? xor edx,edx ; Здесь я буду увеличивать адрес памяти mov ecx, _РАЗМЕР_ФАЙЛА_ metka: movzx ax, WORD PTR buf+[edx] ;Грузим в ax первое слово памяти плюс смещение cmp ax, '0ADh' je dalee inc edx Loop metka1 metka1 dalee: ................................ Примерно так? Это я по своему малому опыту работы со строками в буфере. полагаю, FileMapped это нечто тоже самое? Или там иначе надо сканировать? C уважением, ТОЛСТОПУЗ.
cmp ax, '0ADh' ни в коем случае! в кавычках ты сравниваешь с текстом! и не 0ADh, ибо это байт 0хAD, а тебе надо последовательность 0x0D 0x0A; ворд 0х1234 состоит из дывух байт: 12h и 34h, в памяти он выглядит: 0x34 0x12, то есть в обратном порядке. та что вводя 1234h в файле искаться будет последовательность 34h:12h. так что писать надо просто 0A0Dh. но и читать по два байта, это удобнее при маппинге знаменитом. лучше ищи просто 13й символ и всё тута ¦)
1) либо это самая первая строка тогда смотрим самый первый символ и проверяем его на равенство с '1' 2) либо это сочетание 0Dh,0Ah,31h так как о длине строк мы ничего не знаем , то сравнивать придется по-байтно Допустим весь свой текст ты скопировал в память и на него указывает регистр edi, в регистре ecx находится длина текста в байтах Код (Text): mov al,0Dh mov count,0 a1: repne scasb jecxz quit; из сканирования мы можем выйти по двум причинам ;1) мы прошлись по всему тексту и ничего не нашли (ecx=0) ;2) мы нашли нужный символ cmp word ptr [edi],310Ah; проверяем два следующих символа jne a1 add edi,2 inc count; увеличиваем счетчик строк начинающихся с '1' jmp a1 quit:
первую строку теряем. логика лучше такая: label1: сравниваем симбол с "1" адин: ок, сохраняем позицию, ищем конец строки: не 10 и не eof, идём к следующей букве 10. ок, выводим строчку(типо копируем в буффер, или на место 13 пишем нолик, а потом printf(сохранённая поз."1"), выходим из поиска десятки. неадин: если конец файла - выходим. иначе jmp label1 типо водтак. предельно доступно. допустим он таки освоил маппинг ¦))
Выдрал с ЛИБ МАСМА. Читает в указанный буфер строку, правда вытерает првторные пробелы и ТАБы. Код (Text): LineFromFile proc USES EDI ECX h_file:DWORD,buffer:DWORD LOCAL L_BUF :DWORD LOCAL cb :DWORD LOCAL Cnt :DWORD xor eax, eax ; clear EAX mov [L_BUF], eax mov [Cnt], eax dec [Cnt] mov ebx, [buffer] ; buffer address in EDI ; add edx, [spos] ; add spos to source xor eax, eax ; clear EAX mov ecx, -1 ; set index and counter to -1 jmp ristart align 4 pre: mov [ebx+ecx], al ; write BYTE to buffer ristart: add ecx, 1 push ecx invoke ReadFile,[h_file],ADDR L_BUF,1,ADDR cb,NULL pop ecx .if !eax ret .endif .if ![cb] mov BYTE PTR [ebx+ecx], 0 ; write terminator to buffer xor eax, eax dec eax ret .endif mov eax, [L_BUF] ; read BYTE from source File cmp al, 9 ; handle TAB character je pre cmp al, 13 ; test for ascii 13 and 0 ja pre mov BYTE PTR [ebx+ecx], 0 ; write terminator to buffer push ecx invoke ReadFile,[h_file],ADDR L_BUF,1,ADDR cb,NULL pop ecx .if !eax ret .endif .if ![cb] mov BYTE PTR [ebx+ecx], 0 ; write terminator to buffer xor eax, eax dec eax .endif jz liout ; return zero if end of source lea eax, [ecx+2] ; add counter + 2 to EAX ; return next spos in eax liout: ret LineFromFile endp