SetFilePointer и 13,10

Тема в разделе "WASM.BEGINNERS", создана пользователем TOLSTOPUZ, 27 апр 2008.

  1. TOLSTOPUZ

    TOLSTOPUZ New Member

    Публикаций:
    0
    Регистрация:
    26 апр 2008
    Сообщения:
    509
    Программа должна открыть текстовый файл и найти все строки, начинающиеся на символ 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 ...
    Правда всё это работает... :)
    Помогите новичку, плиз.
     
  2. Com[e]r

    Com[e]r Com[e]r

    Публикаций:
    0
    Регистрация:
    20 апр 2007
    Сообщения:
    2.624
    Адрес:
    ого..
    invoke SetFilePointer, fHandle, 13, 0, FILE_BEGIN
    invoke SetFilePointer, fHandle, 10, 0, FILE_BEGIN
    вотэто янипонял.
    ты сначала переносишь себя на 13й символ, потом 10й.. то ли я так туплю сёдня тооли лыжи задом на перёд одел..
    вобще почему не сделать маппинг(CreateFileMapping+MapViewOfFile) и не сканить буффер вдоль?
     
  3. KeSqueer

    KeSqueer Сергей

    Публикаций:
    0
    Регистрация:
    19 июл 2007
    Сообщения:
    1.183
    Адрес:
    Москва
    А вот это даже странно как-то

    те SetFilePointer если подразумеваются для перехода на символ после 10,13, то неправильно. Если на то пошло, нужно побайтово считывать файл и искать там 13 и следующую за ним 10. Тогда мы и попадем на новую строку.

    насчет красивости перехода. если имеется в виду аскии символ 1, а не байт со значением 1, то нужно вместо 1 писать '1' и buf должно быть инициализировано DWORD (0) перед вызовом ReadFile, если это локальная переменная. Ну и сам переход красивее не сделаешь

    Конец файла находится по значению cRead, которая показывает, сколько байт считано. Если ноль, значит файл кончился

    короче, если совсем уж новичок, сначала продумай алгоритм, по которому ищутся строки, начинающиеся на 1 и как они должны быть представлены на выходе

    вот как то вот так вот
     
  4. Com[e]r

    Com[e]r Com[e]r

    Публикаций:
    0
    Регистрация:
    20 апр 2007
    Сообщения:
    2.624
    Адрес:
    ого..
    а естчо лучше - представь фаел как строку 'abcdefg',13,10,'hijkl'..
    асм это весьма наглядно показал..
    хотя тут пациенту надо и аски учить, и "двухмерные массивы", и логику слушать - что самое сложное..
    это и есть та единственная ситуация, когда я считаю, что лучше бы чел начал с делфи или другога ООЯП. =\

    вот так то как то так вот.
     
  5. Osen

    Osen Рие

    Публикаций:
    0
    Регистрация:
    5 апр 2008
    Сообщения:
    283
    Адрес:
    Париж
    TOLSTOPUZ
    Код (Text):
    1. cmp   buf,'1'                 ; 7 байт
    2. jne    new_str_label       ; 2 байта, если метка в бинарном диаметре не больше 128
    У тебя получается
    Код (Text):
    1. >mov   eax,'1'              ; 5 байт - неправильно, сравниваем байты, правильно дальше
    2. mov     al,'1'                ; 2 байта
    3. >cmp   eax, buf            ; 3 байта - но здесь неправильно, т.к. ты считал байт, а сравниваешь DWORD'ы
    4. >                               ; правильно дальше
    5. cmp     al,[buf]            ; 6 байт
    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, это оптимизирует операции кеширования, учитывая то, что ты будешь читать файл строго последовательно. Однако, если отступить от этого правила будут провалы производительности.
     
  6. valterg

    valterg Active Member

    Публикаций:
    0
    Регистрация:
    19 авг 2004
    Сообщения:
    2.105
    TOLSTOPUZ
    Очень сложно объяснили. SetFilePointer не найдет конца строки. Найди Си-шную фуннкцию, которая это делает - читает строки. Либо тупо ищи символы 13,10. А вот за ними как раз надо искать '1'. А про Filemapping - это как в той рекламе - рано еще такому молодому, УВЫ.
     
  7. Com[e]r

    Com[e]r Com[e]r

    Публикаций:
    0
    Регистрация:
    20 апр 2007
    Сообщения:
    2.624
    Адрес:
    ого..
    да бред!
    чо вы поцана портите? ниуя не рано, если у него "воин зена" написано под ником!
    пусть учится без поблажек, ато ёпт хекеры скоро вымрут нахрен все =\\
    тем более mapping. это не такая уж сложная функция.

    парень на асме пишет, а ты сишную функцию..
    правильно Osen говорит: пусть ищет WORD 0A0Dh (в памяти и на диске эта цифра будет как раз 0D0Ah)..
    /* и НЕ правильно говорит Osen - не 1013h, ибо это байты 19 и 16, не путай мальчика .) */
    ..то есть найдя последовательность 0d,0a ты прибавляешь 2 к указателю (то есть с переноса на строку переходишь к самой строке) и сравниваешь первый символ с 31м символом, или просто с '1'.
    изучи маппинг.
     
  8. TOLSTOPUZ

    TOLSTOPUZ New Member

    Публикаций:
    0
    Регистрация:
    26 апр 2008
    Сообщения:
    509
    Прошу прощения,
    Вы говорите надо искать структуру 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 уважением, ТОЛСТОПУЗ.
     
  9. Com[e]r

    Com[e]r Com[e]r

    Публикаций:
    0
    Регистрация:
    20 апр 2007
    Сообщения:
    2.624
    Адрес:
    ого..
    cmp ax, '0ADh'
    ни в коем случае!
    в кавычках ты сравниваешь с текстом!
    и не 0ADh, ибо это байт 0хAD, а тебе надо последовательность 0x0D 0x0A;
    ворд 0х1234 состоит из дывух байт: 12h и 34h, в памяти он выглядит: 0x34 0x12, то есть в обратном порядке.
    та что вводя 1234h в файле искаться будет последовательность 34h:12h.
    так что писать надо просто 0A0Dh.

    но и читать по два байта, это удобнее при маппинге знаменитом.
    лучше ищи просто 13й символ и всё тута ¦)
     
  10. crypto

    crypto Active Member

    Публикаций:
    0
    Регистрация:
    13 дек 2005
    Сообщения:
    2.533
    TOLSTOPUZ
    fgets, файл нужно открыть с аргументом "rt".
     
  11. Mikl_

    Mikl_ New Member

    Публикаций:
    0
    Регистрация:
    14 ноя 2006
    Сообщения:
    907
    1) либо это самая первая строка тогда смотрим самый первый символ и проверяем его на равенство с '1'
    2) либо это сочетание 0Dh,0Ah,31h
    так как о длине строк мы ничего не знаем , то сравнивать придется по-байтно
    Допустим весь свой текст ты скопировал в память и на него указывает регистр edi, в регистре ecx находится длина текста в байтах
    Код (Text):
    1.        mov al,0Dh
    2.        mov count,0
    3. a1:    repne scasb
    4.        jecxz quit; из сканирования мы можем выйти по двум причинам
    5. ;1) мы прошлись по всему тексту и ничего не нашли (ecx=0)
    6. ;2) мы нашли нужный символ
    7.         cmp word ptr [edi],310Ah; проверяем два следующих символа
    8.         jne a1
    9.         add edi,2        
    10.         inc count; увеличиваем счетчик строк начинающихся с '1'
    11.         jmp a1
    12. quit:
     
  12. Com[e]r

    Com[e]r Com[e]r

    Публикаций:
    0
    Регистрация:
    20 апр 2007
    Сообщения:
    2.624
    Адрес:
    ого..
    первую строку теряем.
    логика лучше такая:

    label1:
    сравниваем симбол с "1"
    адин:
    ок, сохраняем позицию, ищем конец строки:
    не 10 и не eof, идём к следующей букве
    10. ок, выводим строчку(типо копируем в буффер, или на место 13 пишем нолик, а потом printf(сохранённая поз."1"),
    выходим из поиска десятки.
    неадин:
    если конец файла - выходим.
    иначе jmp label1

    типо водтак. предельно доступно.

    допустим он таки освоил маппинг ¦))
     
  13. Mikl_

    Mikl_ New Member

    Публикаций:
    0
    Регистрация:
    14 ноя 2006
    Сообщения:
    907
    Можно было и кусок с маппингом написать, но пусть лучше клиент таки помучается:)
     
  14. S_Alex

    S_Alex Alex

    Публикаций:
    0
    Регистрация:
    27 авг 2004
    Сообщения:
    561
    Адрес:
    Ukraine
    Выдрал с ЛИБ МАСМА.
    Читает в указанный буфер строку, правда вытерает првторные пробелы и ТАБы.

    Код (Text):
    1. LineFromFile proc  USES EDI ECX h_file:DWORD,buffer:DWORD
    2. LOCAL   L_BUF   :DWORD
    3. LOCAL   cb      :DWORD
    4. LOCAL   Cnt     :DWORD
    5.     xor     eax,        eax     ; clear EAX
    6.     mov     [L_BUF],    eax
    7.     mov     [Cnt],      eax
    8.     dec     [Cnt]
    9.     mov ebx, [buffer]           ; buffer address in EDI
    10. ;    add edx, [spos]           ; add spos to source
    11.     xor eax, eax                ; clear EAX
    12.     mov ecx, -1                 ; set index and counter to -1
    13.     jmp ristart
    14.   align 4
    15. pre:
    16.     mov [ebx+ecx], al           ; write BYTE to buffer
    17. ristart:
    18.     add ecx, 1
    19.     push    ecx
    20.     invoke  ReadFile,[h_file],ADDR L_BUF,1,ADDR cb,NULL
    21.     pop     ecx
    22.     .if !eax
    23.         ret    
    24.     .endif
    25.     .if ![cb]
    26.         mov BYTE PTR [ebx+ecx], 0   ; write terminator to buffer
    27.         xor     eax,    eax
    28.         dec     eax    
    29.         ret
    30.     .endif
    31.     mov     eax,    [L_BUF]     ; read BYTE from source File
    32.     cmp     al, 9                   ; handle TAB character
    33.     je      pre
    34.     cmp     al, 13                  ; test for ascii 13 and 0
    35.     ja      pre
    36.     mov BYTE PTR [ebx+ecx], 0   ; write terminator to buffer
    37.     push    ecx
    38.     invoke  ReadFile,[h_file],ADDR L_BUF,1,ADDR cb,NULL
    39.     pop     ecx
    40.     .if !eax
    41.         ret    
    42.     .endif
    43.     .if ![cb]
    44.         mov BYTE PTR [ebx+ecx], 0   ; write terminator to buffer
    45.         xor     eax,    eax
    46.         dec     eax    
    47.     .endif
    48.     jz liout                    ; return zero if end of source
    49.     lea eax, [ecx+2]            ; add counter + 2 to EAX
    50.                                ; return next spos in eax
    51. liout:
    52.     ret
    53. LineFromFile endp