BiN2HeX

Тема в разделе "WASM.A&O", создана пользователем bogrus, 3 июн 2005.

  1. bogrus

    bogrus Active Member

    Публикаций:
    0
    Регистрация:
    24 окт 2003
    Сообщения:
    1.338
    Адрес:
    ukraine
    Дано: 32-х байтная строка ASCII символов ('0','1')

    Получить: шестнадцатиричное представление двоичной строки
    Код (Text):
    1. ;=====================================================
    2. bin_str     db      '10000111011001010100001100100001'
    3. ;=====================================================
    4.             mov     eax,bin_str
    5.             call    bin2hex
    6. ;=====================================================
    7. bin2hex:    lea     edx,[eax+32]
    8.             mov     ecx,0-32
    9. align 16
    10. @@:         movzx   ebx,byte[edx+ecx]
    11.             and     ebx,1
    12.             inc     ecx
    13.             lea     eax,[eax*2+ebx]
    14.             jnz     @b
    15.             ret                     ; eax = 0x87654321
    16. ;=====================================================
    Мне этот вариант кажется тупым
     
  2. cresta

    cresta Active Member

    Публикаций:
    0
    Регистрация:
    13 июн 2004
    Сообщения:
    2.257
    А в чём тупость?



    Можно такой вариант (возможно тоже тупой):


    Код (Text):
    1.           mov eax,offset bin_str
    2.           call bin2hex
    3.  
    4. align 16
    5. bin2hex:  mov edx,eax
    6.           xor ecx,ecx
    7.      @@:  shl eax,1
    8.           add al, byte ptr[edx+ecx]
    9.           sub al,30h
    10.           inc ecx
    11.           cmp ecx,32
    12.           jne @B
    13.           ret




    Так на 1 регистр меньше используется. И быстрее на 9 тиков (118/109). И ebx не изменяется.
     
  3. cresta

    cresta Active Member

    Публикаций:
    0
    Регистрация:
    13 июн 2004
    Сообщения:
    2.257
    Если размер и ebx не поджимают, можно ещё быстрее (69 тиков)


    Код (Text):
    1.           mov eax,offset bin_str
    2.           call bin2hex
    3.  
    4. align 16
    5. bin2hex:  mov ebx,eax
    6.           xor ecx,ecx
    7.      @@:  mov edx,[ebx+ecx*4]
    8.           shl eax,1
    9.           sub dx,3030h
    10.           add al,dl
    11.           shl eax,1
    12.           add al,dh
    13.           bswap edx
    14.           shl eax,1
    15.           sub dx,3030h
    16.           add al,dh
    17.           shl eax,1
    18.           add al,dl
    19.           inc ecx
    20.           cmp ecx,8
    21.           jnz @B
    22.           ret
     
  4. leo

    leo Active Member

    Публикаций:
    0
    Регистрация:
    4 авг 2004
    Сообщения:
    2.542
    Адрес:
    Russia
    bogrus

    Тупость только в том, что ты eax забыл обнулить :))

    А вообще в данном случае тупой вариант ИМХО самый простой и компактный, а зачем тут скорость нужна не знаю.

    Ежели только ради развлечения ;)

    Ну тогда вот вариант с разворотом на 4:
    Код (Text):
    1.     ;eax = offset bin_str
    2.     ;push edi
    3.     lea edi,[eax+32]
    4.     mov ecx,-32
    5.     xor eax,eax
    6.     xor edx,edx
    7. @@: shl eax,4
    8.     mov dl,[edi+ecx]
    9.     add dl,dl
    10.     add dl,[edi+ecx+1]  ;для 4-х бит and на каждый символ можно не делать, т.к. у нас только 30h и 31h
    11.     add dl,dl
    12.     add dl,[edi+ecx+2]
    13.     add dl,dl
    14.     add dl,[edi+ecx+3]
    15.     and dl,0Fh
    16.     add eax,edx
    17.     add ecx,4
    18.     jnz @b
    19.     ;pop edi
    20.     ;ret
     
  5. captain cobalt

    captain cobalt New Member

    Публикаций:
    0
    Регистрация:
    21 дек 2003
    Сообщения:
    222
    Адрес:
    /ru/perm
    Пусть в памяти лежит текстовая строка "1101"

    Загрузим её в ЕАХ, получим ЕАХ=31303131h из-за little-endian.

    Выделим младшие биты каждого байта

    AND EAX,01010101h; EAX=01000101h

    Умножим на магическое число 08040201h

    Подробно этот процесс изображен на рисунке:



    [​IMG]



    Нужные биты собрались вместе, причём в нужном порядке. Можно использовать по назначению. ;)
     
  6. bogrus

    bogrus Active Member

    Публикаций:
    0
    Регистрация:
    24 окт 2003
    Сообщения:
    1.338
    Адрес:
    ukraine
    cresta На PIII твой первый вариант 360 тактов (чтение al после eax), второй 250 тактов, мой всего 80



    leo Зачем eax обнулять? я ж его сдвигаю 32 раза, то что в нем было роли не играет



    captain cobalt Вот-вот, в эту сторону мне и хотелось пораскинуть мозгами
     
  7. cresta

    cresta Active Member

    Публикаций:
    0
    Регистрация:
    13 июн 2004
    Сообщения:
    2.257
    bogrus

    32 перехода jnz в 3 раза быстрее чем 8 переходов?? Мдя... Вот уж действительно народ правду говорит: интел-отстой :) Или дело в shl? Интересно, а если на add eax,eax заменить? На атлоне это одинаково.
     
  8. bogrus

    bogrus Active Member

    Публикаций:
    0
    Регистрация:
    24 окт 2003
    Сообщения:
    1.338
    Адрес:
    ukraine
    cresta Это зависит от тела цикла, твоё ~33 такта, маё ~2.5, вот и умножь на кол-во проходов. А интел не отстой, он простые инструкции может выполнять за 0.25-0.5 такта, а вот атлон, если не ошибаюсь по 1-му на каждую. А тут дело не shl или add, а именно в обращении к части регистра после целого, у leo кстати побыстрее, ~70
     
  9. leo

    leo Active Member

    Публикаций:
    0
    Регистрация:
    4 авг 2004
    Сообщения:
    2.542
    Адрес:
    Russia
    bogrus

    Насчет eax, пардон. А говоришь тупой вариант, это я тупой сразу не сообразил ;)



    Насчет ~70 тиков на PIII. Если без call\ret и c align 16, то у меня получается 63 тика. А супервариант captain cobalt аж 57 !
     
  10. iron_nomad

    iron_nomad New Member

    Публикаций:
    0
    Регистрация:
    27 апр 2005
    Сообщения:
    30
    Интересно а с применением xlat медленней будет?
     
  11. cresta

    cresta Active Member

    Публикаций:
    0
    Регистрация:
    13 июн 2004
    Сообщения:
    2.257
    bogrus

    А откуда эта инфо:


    Если речь о тиках, а не тактах из справочника, то у меня получается ~7.5 и ~3.4 соответственно.



    И add с частью регистра после shl для Pentium'а имеет такие катастрофические последствия?



    leo

    А как ты реализовал
    ?
     
  12. bogrus

    bogrus Active Member

    Публикаций:
    0
    Регистрация:
    24 окт 2003
    Сообщения:
    1.338
    Адрес:
    ukraine
    cresta Из теста на PIII, не во всяком справочнике можно увидеть данные по пенальти, я супервариант сделал пока так (~50):
    Код (Text):
    1. bin2hex:    lea     edx,[eax+32]
    2.             mov     ecx,-32
    3. align 16
    4. @@:         mov     ebx,[edx+ecx]
    5.             and     ebx,0x01010101
    6.             imul    ebx,0x08040201
    7.             shl     ebx,4
    8.             shld    eax,ebx,4
    9.             add     ecx,4
    10.             jnz     @b
     
  13. leo

    leo Active Member

    Публикаций:
    0
    Регистрация:
    4 авг 2004
    Сообщения:
    2.542
    Адрес:
    Russia
    cresta

    > А как ты реализовал „супервариант captain cobalt “?

    По простому ;)
    Код (Text):
    1.     ;push edi, push esi, pus ebx
    2.     lea edi,[eax+32]
    3.     mov ecx,-32
    4.     mov esi,08040201h
    5.     xor ebx,ebx  ;на всякий случай, хотя bogrus учит что не нужно ;)
    6. @@: mov eax,[edi+ecx]
    7.     and eax,01010101h
    8.     mul esi
    9.     shr eax,24
    10.     shl ebx,4
    11.     add ebx,eax
    12.     add ecx,4
    13.     jnz @b
    14.     mov eax,ebx
    15.     ;pop ebx, pop esi, pop edi, ret




    PS: ну вот, пока писАл bogrus уже свой вариант запостил :)
     
  14. bogrus

    bogrus Active Member

    Публикаций:
    0
    Регистрация:
    24 окт 2003
    Сообщения:
    1.338
    Адрес:
    ukraine
    Для удобства сменил константу на 0x80402010, теперь ~40
    Код (Text):
    1. bin2hex:    lea     edx,[eax+32]
    2.             mov     ecx,-32
    3. align 16
    4. @@:         mov     ebx,[edx+ecx]
    5.             and     ebx,0x01010101
    6.             imul    ebx,0x80402010
    7.             shld    eax,ebx,4
    8.             add     ecx,4
    9.             jnz     @b
     
  15. cresta

    cresta Active Member

    Публикаций:
    0
    Регистрация:
    13 июн 2004
    Сообщения:
    2.257
    Интересно, для Атлона получается пенальти либо не возникают, либо они очень слабо сказываются.

    Похоже, вся оптимизация без указания конкретной модели процессора - это пшик :) Надо специально оговаривать: предлагать варианты для PIII или для PIV или для Атлона.:)

    Самые быстрые у меня оказались

    супер leo - 55 тиков (даже с push esi,edi/pop edi,esi)

    мой второй - 69 тиков

    первый leo - 70 тиков

    супер bogrus - 79 тиков
     
  16. S_T_A_S_

    S_T_A_S_ New Member

    Публикаций:
    0
    Регистрация:
    27 окт 2003
    Сообщения:
    1.754
    Оптимизация по размеру (13 байт включая ret и cld)
    Код (Text):
    1.  
    2. ; in:   esi - pointer to ASCII string (32 bytes long)
    3. ; out:  eax - converted hex value
    4.         xor    edx, edx
    5.         cld
    6.         inc    edx
    7. @@:     lodsb
    8.         shr    al, 1
    9.         rcl    edx, 1
    10.         jnc    @b
    11.         xchg   eax, edx
    12.         ret
    ЗЫ: в данном случае счётчик в лишнем регистре не нужен.
     
  17. bogrus

    bogrus Active Member

    Публикаций:
    0
    Регистрация:
    24 окт 2003
    Сообщения:
    1.338
    Адрес:
    ukraine
    cresta Прально, каждый меряет на своем и говорит результат, а при использовании делаешь детект ЦПУ и идешь по нужной ветке, конечно если скорость нуна :)



    [​IMG] 74936217__detect.exe
     
  18. S_T_A_S_

    S_T_A_S_ New Member

    Публикаций:
    0
    Регистрация:
    27 окт 2003
    Сообщения:
    1.754
    13 байт, но не портит esi (fastcall конвенция)
    Код (Text):
    1. bin2hex:
    2.         xor     eax, eax
    3.         inc     eax
    4. @@:     cmp     [byte ecx], 31
    5.         ctc
    6.         inc     ecx
    7.         rcl     eax, 1
    8.         jnb     @b
    9.         retn
     
  19. leo

    leo Active Member

    Публикаций:
    0
    Регистрация:
    4 авг 2004
    Сообщения:
    2.542
    Адрес:
    Russia
    Догадайтесь с 3х попыток какой вариант быстрее на P4 ;)
    Код (Text):
    1. 196  второй вариант cresta (P4 страшно не любит bswap и не долюбливает shl - лучше add ;)
    2. 160  исходный вариант bogrus
    3. 112  первый вариант captain_cobalt & bogrus c shld
    4. 92   последний вариант bogrus с 80402010 и  shld
    5. 84   если в первом варианте заменить shl+shld на shr+shl+add
    6. 64   скромный туповатый вариант leo с разворотом на 4
    Туповатые P4 просто обожают туповатые варианты ;)



    bogrus

    Пральна то пральна, да вот скоко скушает сам детектор ? Может просто не нуна гнаться за рекордами на одном отдельно взятом ?

    PS: похоже Атлон тоже не любит shld, как и P4 ;)
     
  20. leo

    leo Active Member

    Публикаций:
    0
    Регистрация:
    4 авг 2004
    Сообщения:
    2.542
    Адрес:
    Russia
    Если в в последнем симпатичном варианте bogrus'а убрать shld, то наверное всех устроит ;)

    По крайней мере на P3 без потерь, а на P4 - 68 тиков
    Код (Text):
    1. bin2hex:    mov     edx,eax
    2.             mov     ecx,32-4  ;от младших разрядов к старшим
    3. align 16
    4. @@:         mov     ebx,[edx+ecx]  
    5.             and     ebx,0x01010101
    6.             imul    ebx,0x80402010
    7.             and     ebx,0xF0000000 ;<--- !!!
    8.             shr     eax,4
    9.             or      eax,ebx
    10.             sub     ecx,4
    11.             jge     @b
    А как Атлон отреагирует ?



    Исправление: О-о, поспешишь - людей насмешишь. Тут ведь еще нужно and ebx,0xF0000000h добавить :dntknw:

    На P4 эта добавка мало сказывается (результат наполовину 68 или 72, с учетом дискрета 4 тика на P4)