· Начало · Отвђтить · Статистика · Поиск · FAQ · Правила · Установки · Язык · Выход · WASM.RU · Noir.Ru ·

 WASM Phorum —› WASM.ASSEMBLER —› Требуется оптимизировать по скорости.

. 1 . 2 . >>

Посл.отвђт Сообщенiе


Дата: Авг 11, 2004 12:33:51

Требуется оптимизировать по скорости перевод ASCII строки вида
sign1 = 5678ff45::::::0011,0, sign 2= 45454500::ff,0,0 (строка оканчивается на два нуля!)
в которой могут присутствовать пробелы и табуляция
в строку
'sign1',0,5678FF450000000011 , где sign1 осталось в ASCII, всё остальное переведено в HEX
причем получаемая строка должна всё время писаться сначала буфера buff
Т.е. символы :::: должны заменяться на 0000, в идеале нужно чтоб любые не HEX
символы в ASCII представлении заменялись бы 0 нулём.

Я тут набросал первоначальный вариант, но что-то у меня уже крышу сносит,
кажется я не все учёл, а уж что не оптимально так это точно.
  mov esi, src
@loop:
  mov edi, buff
  mov al, BYTE [esi]
  cmp al, 20h  ; пробел
  je @skip
  cmp al, 09h  ; табуляция
  je @skip
@parse:
  test al, al
  jz @test
  cmp al, '='
  je @found
  mov BYTE [edi], al
  inc esi
  inc edi
  mov al, BYTE [esi]
  jmp @parse
@found:
  mov BYTE [edi], 0
  inc edi
  inc esi
@loop3:
  mov ecx, 2
;  xor bl, bl
@loop2:
  lodsb
  test al, al
  jz @test2
  cmp al, 20h  ; пробел
  je @loop2
  cmp al, 09h  ; табуляция
  je @loop2
     shl ebx, 4
     cmp al, 3Fh+1
     sbb edx, edx
     cmp al, 3Ah
     adc edx, 0
     cmp edx, -1
     sbb edx, edx
     and eax, edx
     jz @F
     cmp al, 'f'+1
     sbb edx, edx
     cmp al, 'a'
     adc edx, 0
     and edx, 'A'-'a'
     add al, dl
     cmp al, 'F'+1
     sbb edx, edx
     cmp al, 'A'
     adc edx, 0
     and edx, -07h
     add al, dl
     xor al, 030h
@@:
     or ebx, eax
     loop @loop2
  mov BYTE [edi], bl
  inc edi
  jmp @loop3
;--------------------------------------------------------
@skip:
  inc esi
  jmp @loop
@test:
  mov al, BYTE [esi+1]
@test2:
  test al, al
  jnz @loop


Дата: Авг 11, 2004 13:10:56

Asterix
перевод ASCII строки вида ... в строку ...
Мне не совсем понятна твоя запись.
Можно увидеть исходную строку и результирующую в шестнадцатеричном виде, байты отделены пробелами? И если можно, то пример содержащий пробелы и табуляции и как с ними надо поступисть.


Дата: Авг 11, 2004 13:42:31

А пример можно?


Дата: Авг 11, 2004 13:46:21 · Поправил: Asterix

Исходная строка, оканчивающаяся двумя 0 нулями.
Каждая подстрока в исходной строке в свою очередь оканчивается 0 нулём.
Вывод нужно делать в один и тот же буфер, с его начала, для каждой подстроки.
00550000  73 69 67 6E 31 3D 39 41  sign1=9A
00550008  20 46 46 20 46 46 20 30   FF FF 0
00550010  30 20 30 30 20 39 41 20  0 00 9A
00550018  46 46 46 46 20 30 30 30  FFFF 000
00550020  30 20 35 35 38 39 20 45  0 5589 E
00550028  35 33 31 20 3A 3A 3A 3A  531 ::::
00550030  46 46 30 30 30 30 00 73  FF0000.s
00550038  69 67 6E 20 32 3D 41 31  ign 2=A1
00550040  3A 3A 3A 3A 3A 3A 3A 3A  ::::::::
00550048  43 31 3A 3A 3A 3A 41 33  C1::::A3
00550050  3A 3A 3A 3A 3A 3A 3A 3A  ::::::::
00550058  38 33 3A 3A 3A 3A 3A 3A  83::::::
00550060  3A 3A 37 35 3A 3A 35 37  ::75::57
00550068  35 31 33 33 43 30 42 46  5133C0BF
00550070  00 73 69 67 6E 33 3D 41  .sign3=A
00550078  31 3A 3A 3A 3A 3A 3A 3A  1:::::::
00550080  3A 43 31 3A 3A 3A 3A 41  :C1::::A
00550088  33 3A 3A 3A 3A 3A 3A 3A  3:::::::
00550090  3A 35 37 35 31 33 33 43  :575133C
00550098  30 42 46 3A 3A 3A 3A 3A  0BF:::::
005500A0  3A 3A 3A 42 39 3A 3A 3A  :::B9:::
005500A8  3A 3A 3A 3A 3A 33 42 43  :::::3BC
005500B0  46 37 36 00 00 00 00 00  F76.....


Это результирующая строка, которая должна выводится
для каждой подстроки в строке:
00401008              73 69 67 6E      sign
00401010  31 00 9A FF FF 00 00 9A  1.љяя..љ
00401018  FF FF 00 00 55 89 E5 31  яя..U‰е1
00401020  00 00 FF 00 00           ..я..


> И если можно, то пример содержащий пробелы и табуляции и как с ними надо поступисть

Пробелы до начала строки должны проskip'ываться, пробелы в названии sign 1 должны оставляться.
 sign 1 = 9A FF FF 00 00 9A FFFF 0000 5589 E531 ::::FF0000
|    |   |_этот не нужен   |____|____|эти пробелы не нужны
|    |
|    |_этот нужен
|
|
|
|_этот пробел не нужен

Хотя практически получается что строка возле = не содержит пробелов
на это нельзя рассчитывать.


Дата: Авг 11, 2004 14:23:37 · Поправил: Black_mirror

Asterix
Если внутри сигнатуры могут содержаться нули, как ты определишь где начинается следующая подстрока?

Или мы записываем в буфер первую подстроку, обрабатываем, а затем записываем следующую?

И еще вопрос: как обрабатывать последний символ сигнатуры если их количество нечетное?


Дата: Авг 11, 2004 15:10:49

Black_mirror
Внутри сигнатуры нулей 00h нет, есть только '0'=30h
те нули что там встречаются это концы подстрок

В исходном буфере все подстроки идут подряд:
подстрока1,0,подстрока2,0,подстрока3,0,0 <-это конец т.к. два нуля.

Условимся что четное, т.е. сигнатура, после = будет состоять из четного числа байт(не считая пробелы и табуляцию, с ними может быть и не четное), иначе я вобще не понимаю как это можно правильно перевести из ASCII в HEX.


Дата: Авг 11, 2004 15:20:37 · Поправил: Asterix

src db 'sign1 = 9A FF FF 00 00 9A FFFF 0000 5589 E531 ::::FF0000',0
    db 'sign 2=A1::::::::C1::::A3::::::::83::::::::75::575133C0BF',0
    db 'sign3 =A1::::::::C1::::A3::::::::575133C0BF::::::::B9::::::::3BCF76',0,0


Дата: Авг 11, 2004 17:15:15

Asterix
Я не правильно задал вопрос, если после преобразования подстроки в сигнатуру, внутри сигнатуры окажутся нули, то как ты определишь где начинается следующая сигнатура?

И еше напиши пожалуйста какие символы в подстроке вообще игнорируются и из каких может состоять имя.

PS: Если бы в части подстроки, которая представляет сигнатуру не было бы символов которые нужно игнорировать, то можно было бы преобразовывать сразу по 4 или по 8 символов.


Дата: Авг 11, 2004 17:37:37 · Поправил: Asterix

Black_mirror
> Я не правильно задал вопрос, если после преобразования подстроки в сигнатуру, внутри сигнатуры окажутся нули, то как ты определишь где начинается следующая сигнатура?

Вобще-то я планировал подсчитывать размер сигнатуры в момент преобразования, но здесь пока не реализовал.

> то как ты определишь где начинается следующая сигнатура?

Следующая сигнатура будет вписываться в этот же буфер с самого начала, перекрывая предыдущую, потому что после получения сигнатуры и ее длины эти параметры будут передаваться в процедуру и по результату работы процедуры будет решаться парсить ли src дальше.

> И еше напиши пожалуйста какие символы в подстроке вообще игнорируются и из каких может состоять имя.

В имени могут быть любые символы кроме = , т.к. равно определяет конец имени сигнатуры и начало
собственно ее самой, даже пробельные, в сигнатуре любые не HEX символы, кроме пробельных, должны заменяться на нули, в данном случае это :: дают 00 т.е. нулевой байт, пробельные пропускаться и не входить в итоговую сигнатуру в hex представлении.

В результате преобразования мне нужно получить:
    поинтер на имя сигнатуры(это есть т.к. совпадает с OFFSET buff)
    поинтер на первый байт сигнатуры
    длину сигнатуры


Дата: Авг 11, 2004 18:58:31 · Поправил: Black_mirror

Asterix
Вот как можно по 4 символа сразу обрабатывать:

Четыре символа находящиеся в регистре eax рассматриваются как 16-ричные цифры(биты 7:0 - первая цифра, 31:24 - последная цифра, все что не является цифрой заменяется на 0) и переводятся в два байта(al байт полученный из бит 7:0(старшая цифра) и 15:8(младшая цифра), ah - байт полученный из 23:16 и 31:24). Под bit7 имеетются ввиду старшие биты каждого байта регистра.
hextonum:;(eax - four char):ax - num
;A..F  -> a..f
	mov ecx,40404040h ;перевод букв в верхний регист
	and ecx,eax       ;также могут буть заменены и некоторые другие символы
	shr ecx,1         ;но на правильность работы функции это никак не влияет
	not ecx
	and eax,ecx
;char -> BCD
	lea edx,[eax-'0000']	
	or edx,80808080h ;для избежания распространения переноса в соседние байты
	lea ebx,[edx-'AAAA'+'0000'] ;принадлежит ли байт диапазону A..F	
	lea ecx,[edx-'GGGG'+'0000']
	xor ebx,ecx	;bit7=1 if A..F
	lea ecx,[edx-0A0A0A0Ah] ;принадлежит ли байт диапазону 0..9	
	xor ecx,edx	;bit7=1 if 0..9
	not eax ;bit7=1 if not digit
	xor ecx,ebx	;буква или цифра
	and eax,ecx	;bit7=1 if digit
;if A..F then sub 7
	and ebx,80808080h ; сдвигаем интервал A..F к интервалу 0..9
	shr ebx,4
	sub edx,ebx
	shr ebx,3
	add edx,ebx
;create mask
	and eax,80808080h ;обнуляем все символы не цифры
	mov ecx,eax
	shr ecx,7
	sub eax,ecx	
	and eax,edx	;not digit -> 0
;BCD -> num
	mov edx,eax ;в каждом байте теперь по одной 16-ричной цифре
	shl edx,12  
	add eax,edx
	mov al,ah
	rol eax,8

	xchg al,ah
	ret

Нужно только эффективный метод выкидывания пробелов придумать.

PS: Кстати без всяких if'ов и переходов!


Дата: Авг 11, 2004 21:53:11

Black_mirror
> Нужно только эффективный метод выкидывания пробелов придумать.

Невыполнимо наверно :-(

А что до твоего кода то я практически ничего не понял, думаю тут нужно на бумажке себе всё расписать что на каком шаге происходит.

Давай посмотрим по кускам, вот здесь
cmp al, 20h  ; пробел
  je @skip
  cmp al, 09h  ; табуляция
  je @skip

и
  test al, al
  jz @test2
  cmp al, 20h  ; пробел
  je @loop2
  cmp al, 09h  ; табуляция
  je @loop2

Может можно как-то оптимизировать чтоб остался только один переход?


Дата: Авг 12, 2004 00:08:11 · Поправил: Black_mirror

Asterix
Выкинуть не сложно, только эти переходы срабатывают не часто, так что наверно лучше с ними.
  mov ah,al
  xor eax,2009h
  lea edx,[eax-101h]
  xor edx,eax
  and edx,eax
  xor al,9
  and ebx,8080h
  jnz .skip

или в лоб:
  cmp al,21h
  sbb ebx,ebx
  cmp al,20h
  adc ebx,0
  cmp al,10
  sbb ebx,0
  cmp al,9
  adc ebx,0
  jnz .skip


А для моей функции требуется собрать в eax четыре непробельных символа и она их преобразует в 2 байта сигнатуры. Я еще там малость коментариев дописал.

Для второго участка кода одним переходом не обойтись, там метки 2 разные метки.


Дата: Авг 12, 2004 00:53:16

Black_mirror
> Для второго участка кода одним переходом не обойтись, там метки 2 разные метки

Точно, это не доглядел когда постил.

> А для моей функции требуется собрать в eax четыре непробельных символа и она их преобразует в 2 байта сигнатуры. Я еще там малость коментариев дописал.

Спасибо, с комментариями немного стало понятней.
Ладно, а как функция сработает если 4-е байта не найдется в конце сигнатуры ?

А как проскипать пробелы я кажется понял типа:
 mov ecx, 4
@@:
 lodsb
 test al, al
 jz
 cmp al, 20h
 je @B
 cmp al, 09h
je @B
shl eax, 8
loop @B


Для быстроты конечно нужно будет lodsb и loop заменить.


Дата: Авг 12, 2004 00:59:37

Asterix
„Ладно, а как функция сработает если 4-е байта не найдется в конце сигнатуры ? “
Все зависит от того, что ты ей вместо недостающих байт подсунешь.


Дата: Авг 12, 2004 01:11:54

Да, ещё, как при обработке по 4-е байта посчитать заодно размер сигнатуры?
Хотя сейчас кажется придумал..

> Все зависит от того, что ты ей вместо недостающих байт подсунешь.

Если нули? Кстати если твоя функция припишет в конец итоговой сигнатуры лишние нули и учтет это при подсчёте длины сигнатуры, то это, вобщем-то, на результат работы функции, работающей с полученной сигнатурой не отразится т.к. нули там считаются за любой байт и условие всегда будет верно.

. 1 . 2 . >>


Powered by miniBB 1.6 © 2001-2002
Время загрузки страницы (сек.): 0.059