Forth http://www.fforum.winglion.ru/ |
|
SREAD-LINE перестает видеть переводы строк http://www.fforum.winglion.ru/viewtopic.php?f=20&t=3072 |
Страница 2 из 2 |
Автор: | VoidVolker [ Ср авг 05, 2015 13:49 ] |
Заголовок сообщения: | Re: SREAD-LINE перестает видеть переводы строк |
Проверка файлов в текстовых и HEX редакторах потдверждает корректность файлов и всех переводов строк. Итак, тестовый код (добавлены стековые комментарии для SREAD-LINE): Код: : CRLF-Count \ ( a u -- ) 0 >R BEGIN \ a u DUP \ a u u IF 2DUP \ a u a u CRLF \ a u a u a1 u1 SEARCH \ a u a u a2 u2 ? 0= \ a u a u a2 u2 -? IF \ a u a u a2 u2 2DROP \ a u a u 2DUP \ a u a u a u + \ a u a u a+u 0 \ a u a u a+u 0 2SWAP \ a u a+u 0 a u ELSE \ a u a u a2 u2 2DUP \ a u a u a2 u2 a2 u2 2>R \ a u a u a2 u2 R: a2 u2 NIP \ a u a u u2 R: a2 u2 - \ a u a u-u2 R: a2 u2 2R> \ a u a u-u2 a2 u2 2 \ a u a u-u2 a2 u2 2 /STRING \ a u a u-u2 a2+2 u2-2 2SWAP \ a u a2+2 u2-2 a u-u2 THEN TRUE ELSE 2DUP FALSE \ a u a u ? THEN OK WHILE 2DROP \ R@ . . . CR R> 1+ >R REPEAT 2DROP 2DROP R> . CR ; : crlfCounterTest 0 -ROT OVER + SWAP DO I C@ 0x0D = I 1+ C@ 0x0A = AND IF 1+ THEN LOOP . CR ; И результат у меня такой получается: Код: S" TestFile.txt" FILE crlfCounterTest 180000 И вот такой: Код: S" TestFile.txt" FILE CRLF-Count ... Ok ( 83732948 1310720 83732940 6 4294967295(-1) ) Ok ( 85043668 0 83732948 1310720 4294967295(-1) ) Ok ( 85043668 0 85043668 0 0 ) 13817 SREAD-LINE Возвращает флаг, найденную строку и следующую строку. 83732948 1310720 - следующая строка 83732940 6 - найденная строка Очевидно, что именно на этой найденной строке и происходит остановка поиска. Посмотрим что там внутри: Код: 99789268 32 DUMP 5F2A9D4 32 34 33 31 35 34 0D 0A 34 34 35 36 37 35 0D 0A 243154..445675.. 5F2A9E4 35 35 30 39 30 39 0D 0A 33 33 38 34 34 31 0D 0A 550909..338441.. Ok Как видно - в строке все хорошо. Проверим результат поиска: Код: 99789268 1310720 CRLF SEARCH . . . 0 1310720 99789268 Ok Опаньки! Как это так? Попробуем еще раз: Код: 99789268 1310720 S" 445675" SEARCH . . . 0 1310720 99789268 Ok 99789268 1310720 S" 243154" SEARCH . . . 0 1310720 99789268 Ok Хмм... Все становистя еще интереснее. А если вот так: Код: 99789268 1310719 CRLF SEARCH . . . -1 1310713 99789274 Ok 99789268 1310721 CRLF SEARCH . . . -1 1310715 99789274 Ok 99789267 1310720 CRLF SEARCH . . . 0 1310720 99789267 Ok 99789269 1310720 CRLF SEARCH . . . 0 1310720 99789269 Ok Очевидно, проблема в длине строки - именно эту длину строки поиск не принимает. Интересно, почему же? Посмотрим-ка что это за число более внимательно: Код: 1310720 .H 00140000 Ok 1310720 .B 0000 0000 0001 0100 0000 0000 0000 0000 Ok Интересное число, не правда ли? Проверим-ка одну теорию: Код: 99789267 65535 CRLF SEARCH . . . -1 65528 99789274 Ok Работает. И еще разок: Код: 99789267 65536 CRLF SEARCH . . . 0 65536 99789267 Ok Не работает. Теперь причина такого поведения поиска вполне очевидна: Код: 65535 = 0xFFFF = 0b 0000 0000 0000 0001 0000 0000 0000 0000 65536 = 0x10000 = 0b 0000 0000 0000 0001 0000 0000 0000 0000 Поиск шестандцатибитный. Т.е., максимальная длина строки, в которой производится поиск составляет 65535. Тот же самый код в SPF4 ведет себя как ожидается - поиск там 32-х битный: Код: S" E:\TEMP\Count\TestFile.txt" FILE CRLF-Count 180000 Ok Проблема в команде JCXZ @@1 - её надо заменить на JECXZ @@1 и поиск будет работать на 32 битных строках. Исправленный поиск: Код: CODE SEARCH ( c-addr1 u1 c-addr2 u2 -- c-addr3 u3 flag ) \ 94 STRING Произвести поиск в строке, заданной c-addr1 u1, строки, заданной c-addr2 u2. Если флаг "истина", совпадение найдено по адресу c-addr3 с оставшимися u3 символами. Если флаг "ложь", совпадения не найдено, и c-addr3 есть c-addr1, и u3 есть u1. PUSH EDI CLD MOV EBX, [EBP] OR EBX, EBX JZ @@5 MOV EDX, 8 [EBP] MOV EDI, 0x0C [EBP] ADD EDX, EDI @@4: MOV ESI, 4 [EBP] LODS BYTE MOV ECX, EDX SUB ECX, EDI JECXZ @@1 REPNZ SCAS BYTE JNZ @@1 \ во всей строке нет первого символа искомой строки CMP EBX, # 1 JZ @@2 \ искомая строка имела длину 1 и найдена MOV ECX, EBX DEC ECX MOV EAX, EDX SUB EAX, EDI CMP EAX, ECX JC @@1 \ остаток строки короче искомой строки PUSH EDI REPZ CMPS BYTE POP EDI JNZ @@4 @@2: DEC EDI \ нашли полное совпадение SUB EDX, EDI MOV 0x0C [EBP], EDI MOV 8 [EBP], EDX @@5: MOV EAX, # -1 JMP @@3 @@1: XOR EAX, EAX @@3: ADD EBP, # 4 MOV [EBP], EAX POP EDI RET END-CODE Для применения исправления необходимо подключить ассемблер из дистрибутива SPF4. Либо воспользоваться простым хаком (достаточно один раз вызвать в nncron.ini или в подключенном плагине): Код: 0x90 ' SEARCH 29 + C! Если я правильно понял ман по асму, то по этому адресу находится префикс для команды (0x66/0x67) JECXZ, который переключает разрядность данных, с которыми работает данная команда. Данный хак просто заменяет префикс на команду NOP. Но если честно, я сам не все понял тут и возможно данное решение неправильно и я где-то ошибся ) (Не совсем понятна логика ассемблера СПФ для команд JECXZ и JCXZ и добавление префикса). |
Автор: | gudleifr [ Ср авг 05, 2015 14:30 ] |
Заголовок сообщения: | Re: SREAD-LINE перестает видеть переводы строк |
VoidVolker писал(а): Но если честно, я сам не все понял тут и возможно данное решение неправильно и я где-то ошибся ) Все правильно. Я тупо искал, где в асм-е пропущено "E", но JCXZ просмотрел. |
Автор: | makrus [ Чт авг 06, 2015 14:27 ] |
Заголовок сообщения: | Re: SREAD-LINE перестает видеть переводы строк |
VoidVolker писал(а): Но если честно, я сам не все понял тут и возможно данное решение неправильно и я где-то ошибся ) Большущее спасибо за проделанную работу.Я, к сожалению, понял еще меньше, но главное работает! gudleifr, тоже спасибо за активное участие! |
Автор: | VoidVolker [ Пт авг 07, 2015 13:44 ] |
Заголовок сообщения: | Re: SREAD-LINE перестает видеть переводы строк |
makrus http://www.nncron.ru/forums/viewtopic.php?f=5&t=13237 |
Страница 2 из 2 | Часовой пояс: UTC + 3 часа [ Летнее время ] |
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group http://www.phpbb.com/ |