Hex --> ASCII-строка

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

  1. Mikl___

    Mikl___ Супермодератор Команда форума

    Публикаций:
    14
    Регистрация:
    25 июн 2008
    Сообщения:
    3.792
    Типичный пример, который преподаватели любят задавать начинающим изучать ассемблер – написать программу преобразующую двоичное число находящееся, например в регистре EAX в строку символов и вывести ее на экран или в файл. Ниже показаны два варианта такой программы, использующей условные переходы:
    Код (Text):
    1. 1)  mov ecx,8; количество цифр в строке
    2.     mov edi,offset String; адрес строки в edi
    3. @@: rol eax,4; преобразуемое число в регистре eax
    4.     push eax
    5.     cmp al,9;если al < 10, CF = 1
    6.     ja a1  
    7.     add al,'0'
    8.     jmp short a2
    9. a1:     add al,'7'
    10. a2: stosb; помещаем значение из AL в строку
    11.     pop eax
    12.     loop @b; уменьшаем счетчик
    13. ----------------------------------------------------
    14. 2)          add al,'0'
    15.         cmp al,'9'; если al < 10, CF = 1
    16.     jbe a1     
    17.     add al,7
    18. a1: stosb; помещаем значение из AL в строку
    Для увеличения скорости выполнения программы, стараются как можно реже использовать условные переходы. Та же самая задача при использовании команд DAS и DAA может быть выполнена следующим образом:
    Код (Text):
    1. 3)  mov edi,offset String; адрес строки в edi
    2.     mov ecx,4
    3. @@: rol eax,8
    4.     push eax
    5.     push eax
    6.     shr al,4; работаем со старшей тетрадой
    7.     call Hex2
    8.         pop eax
    9.         and al,0Fh; обнуляем старшую тетраду
    10.     call Hex2; работаем с младшей тетрадой
    11.     pop eax
    12.     loop @b
    13.     ...
    14. Hex2:   add al,90h ;если в al была цифра 0..9, тогда в al
    15.            ;будет 90h..99h, если в al была цифра 0Ah..0Fh,
    16.            ;тогда в al будет 9Ah..9Fh
    17.     daa        ; 0-9: 90h..99h CF=0
    18.                ; A-F: 00h..05h CF=1
    19.     adc al,40h ; 0-9: D0h..D9h
    20.                ; A-F: 41h..46h
    21.     daa    ; 0-9: 30h..39h
    22.                ; A-F: 41h..46h
    23.     stosb      ; помещаем значение из AL в строку
    24.     ret
    25. -----------------------------------------------------
    26. 4)          cmp al,10 ; если al < 10, CF = 1
    27.     sbb al,69h;если в al была цифра 0..9, тогда в al
    28.           ;будет 96h..9Fh, если в al была цифра 0Ah..0Fh,
    29.           ;тогда в al будет 0A1h..0A6h
    30.         das       ; 0-9: 96h..9Fh минус 66h -> 30h..39h,
    31.                   ; A-F: 0A1h..0A6h минус 60h -> 41h..46h
    32.     stosb     ; помещаем значение из AL в строку
    33. -------------------------------------------------------
    34. 5)  and al,0Fh; обнуляем старшую тетраду
    35.     cmp al,10; если al < 10, CF = 1
    36.     sbb ah,ah; если al < 10, то ah=0, иначе ah=0FFh
    37.     and ah,1; сбрасываем CF, ah = ah&1 (в ah окажется 0 или 1)
    38.         daa; если в al было 0..9, тогда содержимое al не изменится  
    39.     add al,'1'; если в al было A..F тогда в al стало 10h..15h
    40.     sub al,ah
    41.     stosb; помещаем значение из AL в строку
    42. -------------------------------------------------------
    43. 6)  and eax,0Fh; обнуляем старшую тетраду
    44.     cmp al,10; если al < 10, CF = 1
    45.     adc ah,0; если al < 10, то ah=1, иначе ah=0
    46.         daa; если в al было 0..9, тогда содержимое al не изменится  
    47.     add al,'1'; если в al было A..F тогда в al стало 10h..15h
    48.     sub al,ah
    49.     stosb; помещаем значение из AL в строку
    50. ---------------------------------------------------------
    51. 7)  and eax,0Fh; обнуляем старшую тетраду
    52.     cmp al,10; если al < 10, CF = 1
    53.     sbb ebx,ebx; если al < 10, то ebx=-1, иначе ebx=0
    54.     and ebx,ebx; сброс CF и AF
    55.         daa; если в al было 0..9, тогда содержимое al не изменится  
    56.     lea eax,[ebx+eax+31h];add al,'1'; если в al было A..F тогда в al стало 10h..15h
    57.     stosb; помещаем значение из AL в строку
    58. ------------------------------------------------------------
    59. 8)  cmp al,10;если al < 10, CF = 1
    60.     sbb ebx,ebx; если al < 10, то ebx=0, иначе ebx=-1 CF=AF=1
    61.     daa ; если в al было A..F, тогда al равно 10h..15h
    62.     and ebx,-103; если 0..9, тогда al равно 66h..6Fh 
    63.     lea eax,[eax+ebx+31h]; если A..F, тогда al равно 41h..46h
    64.     stosb; помещаем значение из AL в строку
    65. -------------------------------------------------------------
    66. 9)  and al,0Fh; обнуляем старшую тетраду
    67.     cmp al,10;если al < 10, CF = 1
    68.     sbb ebx,ebx; если СF=0, то ebx=0, иначе ebx=-1
    69.     and ebx,-13; сбрасываем CF и AF, в ebx окажется 0 или -13
    70.     das; если 0..9, тогда al не изменится
    71.     lea eax,[eax+ebx+3Dh]; если A..F, тогда al равно 3..9
    72.     stosb; помещаем значение из AL в строку
    73. ----------------------------------------------------------
    74. 10)         and al,0Fh; обнуляем старшую тетраду
    75.         cmp al,10; если al < 10, CF = 1
    76.     sbb ebx,ebx; если СF=0, то ebx=0, иначе ebx=-1 CF=AF=1
    77.     das; если 0..9, тогда al не изменится
    78.     and ebx,-167; если A..F, тогда al равно 3..9
    79.     lea eax,[eax+ebx+3Dh]
    80.     stosb; помещаем значение из AL в строку
    Вариант с использованием команды XLAT, где-то в сегменте данных должна быть таблица перекодировки:
    table db '0123456789ABCDEF'
    Код (Text):
    1.         and al,0Fh; обнуляем старшую тетраду
    2.     xlat
    3.         stosb; помещаем значение из AL в строку
    Вариант с использованием команды условной пересылки CMOVcc:
    Код (Text):
    1.         mov ecx,8; количество цифр в строке
    2.         mov edi,offset String; адрес строки в edi
    3.         mov bl,30h
    4. @@:         rol eax,4
    5.         push eax; преобразуемое число в регистре eax
    6.         and al,0Fh; обнуляем старшую тетраду
    7.         mov dl,37h
    8.         cmp al,10
    9.         cmovb edx,ebx
    10.         add al,dl
    11.         stosb; помещаем значение из AL в строку    
    12.         pop eax
    13.         shr eax,4; переходим к следующей тетраде
    14.         loop @b; уменьшаем счетчик
    Вариант без использования условного ветвления:
    Код (Text):
    1.         and al,0Fh; обнуляем старшую тетраду
    2.         cmp al,10
    3.     sbb ebx,ebx; если СF=0, то ebx= 0, иначе ebx=-1
    4.     and ebx,-7; в ebx окажется 0 или -7
    5.     lea eax,[eax+ebx+37h]
    6.     stosb; помещаем значение из AL в строку
     
  2. MSoft

    MSoft New Member

    Публикаций:
    0
    Регистрация:
    16 дек 2006
    Сообщения:
    2.854
    Предлагаю закрепить эту тему :) Ну или вынести маленькой отдельной статьей. Ведь алгоритмы действительно интересные и полезные, и искать их потом по форуму будет проблематично.
     
  3. Mikl___

    Mikl___ Супермодератор Команда форума

    Публикаций:
    14
    Регистрация:
    25 июн 2008
    Сообщения:
    3.792
    В догонку
    Код (Text):
    1. 11) and al,0Fh
    2.     cmp al,10
    3.     cmc       ; если al < 10, CF = 0
    4.     adc al,30h;если в al была цифра 0..9, тогда в al
    5. ;будет 30h..39h, если в al была цифра 0Ah..0Fh, тогда в al будет 3Bh..40h
    6.     daa       ; 0-9: 30h..39h,
    7.                   ; A-F: 3Bh..40h плюс 6 -> 41h..46h
    8.     stosb     ; помещаем значение из AL в строку
     
  4. leo

    leo Active Member

    Публикаций:
    0
    Регистрация:
    4 авг 2004
    Сообщения:
    2.542
    Адрес:
    Russia
    Да, тема древняя, но найти сходу симпатичные варианты не так просто - вот с трудом отыскал вариант Black_mirror'a
     
  5. murder

    murder Member

    Публикаций:
    0
    Регистрация:
    3 июн 2007
    Сообщения:
    628
    Для разнообразия можно задействовать MMX
    Код (Text):
    1. x      dd 0FACD123h
    2. mask   dq 0F0F0F0F0F0F0F0Fh
    3. ascii  dq 3030303030303030h
    4. hex    dq 3939393939393939h
    5. ascii2 dq 0707070707070707h
    6. s      rb 9
    7. --//--
    8. pxor      mm0,mm0
    9. punpcklbw mm0,qword[x]
    10. movq      mm1,mm0
    11. psrlw     mm1,12
    12. por       mm0,mm1
    13. pand      mm0,[mask]
    14. paddusb   mm0,[ascii]
    15. movq      mm1,[hex]
    16. pcmpgtb   mm1,mm0
    17. pandn     mm1,[ascii2]
    18. paddusb   mm0,mm1
    19. pshufw    mm0,mm0,00011011b
    20. movq      qword[s],mm0
     
  6. t00x

    t00x New Member

    Публикаций:
    0
    Регистрация:
    15 фев 2007
    Сообщения:
    1.921
    тогда лучше загрузить mask, ascii, hex и ascii2 в свободные регистры mmx и использовать это на очень длинных начальных данных.
     
  7. Mikl___

    Mikl___ Супермодератор Команда форума

    Публикаций:
    14
    Регистрация:
    25 июн 2008
    Сообщения:
    3.792
    "Продолжаем разговор" :) (©"Малыш и Карлсон, который живет на крыше")
    Код (Text):
    1. 12) and al,0Fh; обнуляем старшую тетраду
    2.             daa  ;F->15h            1->1
    3.     add al,0F0h;F0+15h->05h CF=1    F0+1->F1 CF=0
    4.     adc al,40h ;46h         31h
    5.            stosb; помещаем значение из AL в строку
    6. 12)         and al,0Fh; обнуляем старшую тетраду
    7.             daa ; F->15h            1->1
    8.     add al,70h; 70h+15h->85h SF=1 70h+1->71h SF=0
    9.     cbw ; ah=0FFh   ah=0
    10.     sub al,ah   ; 85+1->86h     71h
    11.     sub al,40h; 46h         31h
    12.            stosb; помещаем значение из AL в строку
    13. 13)         and al,0Fh; обнуляем старшую тетраду
    14.             sub al,11h;  F->FEh 1->F0h
    15.     db 0D4h,0F9h;FE->0105h      F0->00F0h
    16.             add al,41h  ;05+41->46h   F0+41->31h
    17.     stosb; помещаем значение из AL в строку
    18. 14)         and al,0Fh; обнуляем старшую тетраду
    19.             aam;         0F->105h   01->0001
    20.     db 0D5h,11h; 105h->16h  0001->01
    21.     add al,30h  ;16+30->46h 01+30->31h
    22.            stosb; помещаем значение из AL в строку
    23. 15)         and ax,0Fh; обнуляем старшую тетраду
    24.             aaa;         0F->105h   01->0001
    25.     db 0D5h,11h; 105h->16h  0001->01
    26.     add al,30h  ;16+30->46h 01+30->31h
    27.            stosb; помещаем значение из AL в строку
     
  8. Jupiter

    Jupiter Jupiter

    Публикаций:
    0
    Регистрация:
    12 авг 2004
    Сообщения:
    532
    Адрес:
    Russia
    интересует решение для заведомо больших блоков данных, например вывод в ascii hex данных дампа
     
  9. Rockphorr

    Rockphorr Well-Known Member

    Публикаций:
    0
    Регистрация:
    9 июн 2004
    Сообщения:
    2.622
    Адрес:
    Russia
    По поводу строки вы сказали слишком мало - стока представлеяет собой десятичное или хекс инвариант ??
    надо по форуму поискать rain вроде поднимал подобную тему ...
     
  10. Rockphorr

    Rockphorr Well-Known Member

    Публикаций:
    0
    Регистрация:
    9 июн 2004
    Сообщения:
    2.622
    Адрес:
    Russia
    нашел вот она
    пардон не rain а proffi
    http://wasm.ru/forum/viewtopic.php?id=14712