Blog. Just Blog

Быстрый поиск

Введите фрагмент названия статьи для поиска

Замена подстроки в строке на Ассемблере

28.03.2012 | Категория: Образ мышления: Assembler | Автор: ManHunter
Во всех языках высокого уровня среди функций работы со строками присутствуют функции замены заданной подстроки в строке. В Ассемблере такой функции нет, как нет ее и среди функций стандартных библиотек. Замена подстроки на строку такой же длины обычно сложностей не составляет, так как ее можно выполнить прямо в исходной строке без выделения дополнительной памяти. Замена на строку произвольной длины, в том числе и пустую, будет посложнее. Для этого я написал следующую функцию.
  1. ;-----------------------------------------------------
  2. ; Функция замены подстроки в строке
  3. ;-----------------------------------------------------
  4. ; lpSrc - указатель на исходную строку
  5. ; lpDst - указатель на буфер для полученной строки
  6. ; lpPattern - указатель на заменяемую подстроку
  7. ; lpReplace - указатель на строку для замены
  8. ; dNum - количество замен (0 - заменить все)
  9. ;-----------------------------------------------------
  10. proc    _replace lpSrc:DWORD, lpPattern:DWORD, lpReplace:DWORD,\
  11.                  lpDst:DWORD, dNum:DWORD
  12.  
  13.         pusha
  14.  
  15.         ; Указатель на буфер-приемник
  16.         mov     edx,[lpDst]
  17.  
  18.         ; Счетчик замен
  19.         xor     ebx,ebx
  20.  
  21.         ; Исходная строка не пустая?
  22.         mov     ecx,[lpSrc]
  23.         cmp     byte [ecx],0
  24.         jz      .loc_ret
  25.  
  26.         ; Заменяемая строка не пустая?
  27.         mov     eax,[lpPattern]
  28.         cmp     byte [eax],0
  29.         jz      .loc_copy_all
  30.  
  31. .loc_scan:
  32.         mov     esi,ecx
  33.         mov     edi,[lpPattern]
  34.  
  35.         ; Исходная строка закончилась?
  36.         cmp     byte [esi],0
  37.         je      .loc_end_replace
  38. @@:
  39.         ; Строки совпали с паттерном?
  40.         cmp     byte [edi],0
  41.         je      .loc_move_replace
  42.  
  43.         ; Символ совпадает с
  44.         lodsb
  45.  
  46.         ; Заменять все вхождения?
  47.         cmp     [dNum],0
  48.         je      .loc_skip_counter
  49.  
  50.         ; Уже заменили нужное количество?
  51.         cmp     ebx,[dNum]
  52.         je      .loc_move_one_char
  53. .loc_skip_counter:
  54.         cmp     al,byte [edi]
  55.         jne     .loc_move_one_char
  56.  
  57.         inc     edi
  58.         jmp     @b
  59.  
  60. .loc_move_replace:
  61.         ; Увеличить счетчик замен
  62.         inc     ebx
  63.  
  64.         mov     ecx,esi
  65.  
  66.         ; Записать заменяющую строку
  67.         mov     esi,[lpReplace]
  68.         mov     edi,edx
  69. @@:
  70.         lodsb
  71.         or      al,al
  72.         jz      .loc_scan
  73.         stosb
  74.         inc     edx
  75.         jmp     @b
  76.  
  77. .loc_move_one_char:
  78.         ; Скопировать один символ
  79.         mov     al,byte [ecx]
  80.         mov     byte [edx],al
  81.         inc     edx
  82.         inc     ecx
  83.         jmp     .loc_scan
  84.  
  85. .loc_end_replace:
  86.         ; Записать финальный 0 в строку
  87.         mov     byte [edx],0
  88.  
  89.         jmp     .loc_ret
  90. .loc_copy_all:
  91.         ; Просто скопировать исходную строку
  92.         mov     esi,[lpSrc]
  93.         mov     edi,[lpDst]
  94. @@:
  95.         lodsb
  96.         stosb
  97.         or      al,al
  98.         jnz     @b
  99. .loc_ret:
  100.         popa
  101.         ret
  102. endp
Функция самодостаточная, не использует никаких внешних функций и не требует для своей работы дополнительных переменных в памяти. Параметры: lpSrc - указатель на исходную строку в формате ASCIIZ, lpPattern - указатель на искомую подстроку в формате ASCIIZ, lpReplace - указатель на строку для замены в формате ASCIIZ, может быть пустая строка, lpDst - указатель на буфер-приемник полученной после замены строки, его размер должен быть зарезервирован с учетом замененных строк, dNum - количество замен, которое надо выполнить (0 - заменять все вхождения). Я постарался оптимизировать функцию замены по скорости, но, наверное, можно ее ускорить как-нибудь еще.

Читать статью целиком »
Просмотров: 11740 | Комментариев: 8

Несколько полезных функций на Ассемблере

21.05.2011 | Категория: Образ мышления: Assembler | Автор: ManHunter

Несколько полезных функций на Ассемблере

За время программирования на Ассемблере у меня накопилось несколько полезных решений. Выделять под каждое из них отдельную статью не хочется, а держать под рукой пригодится. Поэтому все сложу сюда, по мере надобности буду пополнять.

Читать статью целиком »
Просмотров: 29100 | Комментариев: 34

Сортировка массива строк на Ассемблере

29.01.2009 | Категория: Образ мышления: Assembler | Автор: ManHunter
Долго откладывал написание этой функции, но теперь вот прижало. Получилась функция сортировки массива произвольных текстовых строк в формате ASCIIZ усовершенствованным методом "пузырька". Усовершенствование заключается в том, что если при очередном проходе ни одной сортировки не было выполнено, то дальнейшая обработка массива прекращается. В некоторых случаях это дает значительный выигрыш в скорости работы. Однако, алгоритм сортировки "пузырьком" в любом случае является самым медленным, поэтому для очень больших массивов эта функция не подойдет. Но мне для больших объемов ее и не надо, на массиве из нескольких сотен или даже тысяч строк скорость работы функции меня вполне устраивает.
  1. ;------------------------------------------------------------------
  2. ; Функция сортировки массива строк
  3. ; by ManHunter / PCL
  4. ; http://www.manhunter.ru
  5. ;
  6. ; Сортировка выполняется усовершенствованным методом "пузырька"
  7. ; Параметры:
  8. ; lpArray - указатель на массив адресов строк
  9. ; dFlag   - метод сортировки: TRUE - по возрастанию,
  10. ;           FALSE - по убыванию
  11. ; На выходе:
  12. ; отсортированный согласно правилу массив адресов строк
  13. ;------------------------------------------------------------------
  14. proc    SortArray lpArray:dword, dFlag:dword
  15.         pusha
  16.  
  17.         ; Указатель на массив адресов строк
  18.         mov     esi,[lpArray]
  19.  
  20.         mov     ebx,[dFlag]
  21. sa_sort_1:
  22.         ; Проверка на 0 - признак окончания массива
  23.         mov     eax,[esi]
  24.         or      eax,eax
  25.         jz      sa_stop_sort
  26.  
  27.         or      bh,bh
  28.         jnz     sa_stop_sort
  29.  
  30.         ; Сравниваем, начиная со следующего элемента
  31.         lea     edi,[esi+4]
  32.  
  33.         ; Установить флаг, что сортировка не требуется,
  34.         ; если дальнейший остаток массива уже отсортирован
  35.         mov     bh,1
  36. sa_sort_2:
  37.         ; Следующий элемент 0 - массив закончился
  38.         mov     edx,[edi]
  39.         or      edx,edx
  40.         jz      sa_next_sort
  41.  
  42.         ; Сохранить текущие значения указателей
  43.         push    esi edi
  44.  
  45.         ; Указатели на строки
  46.         mov     esi,eax
  47.         mov     edi,edx
  48. sa_compare_string:
  49.         ; Сравнить символы в строках
  50.         mov     cl,byte [edi]
  51.         mov     ch,byte [esi]
  52.         ; Если символы равны, то сравнить следующие
  53.         cmp     cl,ch
  54.         je      sa_equal
  55.  
  56.         ; Проверка больше-меньше в зависимости от флага
  57.         cmp     bl,0
  58.         jz      @f
  59.  
  60.         cmp     cl,ch
  61.         ja      ss_next_string
  62.         jmp     sa_change_offs
  63. @@:
  64.         cmp     cl,ch
  65.         jb      ss_next_string
  66.  
  67. sa_change_offs:
  68.         ; Поменять местами адреса строк
  69.         xchg    eax,edx
  70.         ; Сбросить флаг, что сортировка не требуется
  71.         xor     bh,bh
  72.         jmp     ss_next_string
  73.  
  74. sa_equal:
  75.         ; Если закончилась строка, то перейти к следующей паре
  76.         or      cl,cl
  77.         jz      ss_next_string
  78.  
  79.         ; Перейти к следующей паре символов
  80.         inc     esi
  81.         inc     edi
  82.         jmp     sa_compare_string
  83.  
  84. ss_next_string:
  85.         ; Восстановить значения указателей и записать в них
  86.         ; значения адресов строк, без разницы изменившихся или нет
  87.         pop     edi esi
  88.         mov     [esi],eax
  89.         mov     [edi],edx
  90.  
  91.         ; Перейти к следующему элементу массива
  92.         add     edi,4
  93.         jmp     sa_sort_2
  94.  
  95. sa_next_sort:
  96.         ; Перейти к следующему элементу массива
  97.         add     esi,4
  98.         jmp     sa_sort_1
  99.  
  100. sa_stop_sort:
  101.         popa
  102.         ret
  103. endp
Сортировать сами строки в памяти слишком нерационально, поэтому для сортировки нам понадобится массив DWORD'ов с указателями на строки. Параметр lpArray - указатель на такой массив. Признак окончания массива - DWORD с нулевым значением. Параметр dFlag определяет в каком порядке будет отсортирован массив: по возрастанию (значение TRUE) или по убыванию (значение FALSE). На выходе получаем отсортированный массив указателей.

Читать статью целиком »
Просмотров: 18660 | Комментариев: 7

Функции base64 на Ассемблере

09.01.2009 | Категория: Образ мышления: Assembler | Автор: ManHunter
Алгоритм Base64 может использоваться в пользовательских почтовых приложениях, в качестве одного из уровней защиты шифрованием, для хранения двоичных данных и для решения многих других задачах. В большинстве языков высокого уровня используются штатные функции, в Ассемблере приходится все реализовывать самостоятельно.

Алгоритм Base64 обратимый, то есть из закодированного текста можно в точности получить исходные данные. Начнем с функции кодирования.
  1. ;---------------------------------------------------------------
  2. ; Функция кодирования Base64
  3. ;---------------------------------------------------------------
  4. ; Параметры:
  5. ; lpFrom - указатель на исходные данные
  6. ; lpTo   - указатель на буфер для приема кодированных данных
  7. ; dSize  - размер исходных данных
  8. ; Функция ничего не возвращает
  9. ;---------------------------------------------------------------
  10. proc    base64_encode lpFrom:dword, lpTo:dword, dSize:dword
  11.         pusha
  12.  
  13.         mov     ebx,.base64
  14.         mov     esi,[lpFrom]
  15.         mov     edi,[lpTo]
  16.         mov     ecx,[dSize]
  17.  
  18.         or      ecx,ecx
  19.         jz      .r3
  20. .encode_loop:
  21.         lodsd
  22.         mov     edx,eax
  23.         bswap   edx
  24.         xor     eax,eax
  25.  
  26.         shld    eax,edx,6
  27.         shl     edx,6
  28.         xlatb
  29.         stosb
  30.  
  31.         xor     eax,eax
  32.         shld    eax,edx,6
  33.         shl     edx,6
  34.         xlatb
  35.         stosb
  36.         dec     ecx
  37.         jz      .r2
  38.  
  39.         xor     eax,eax
  40.         shld    eax,edx,6
  41.         shl     edx,6
  42.         xlatb
  43.         stosb
  44.         dec     ecx
  45.         jz      .r1
  46.  
  47.         xor     eax,eax
  48.         shld    eax,edx,6
  49.         shl     edx,6
  50.         xlatb
  51.         stosb
  52.  
  53.         dec     esi
  54.         dec     ecx
  55.         jnz     .encode_loop
  56.  
  57.         jmp     .r3
  58. .r2:
  59.         mov     al,'='
  60.         stosb
  61. .r1:
  62.         mov     al,'='
  63.         stosb
  64. .r3:
  65.         xor     eax,eax
  66.         stosb
  67.         popa
  68.  
  69.         ret
  70.  
  71. .base64 db 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
  72.         db 'abcdefghijklmnopqrstuvwxyz'
  73.         db '0123456789+/'
  74. endp
Параметры вызова: lpFrom - указатель на кодируемые данные, lpTo - указатель на буфер для приема кодированных данных и dSize - размер кодируемых данных. Все параметры обязательные. Размер буфера-приемника должен быть примерно в 1,3 раза больше исходных данных, это обусловлено особенностями алгоритма кодирования.

Читать статью целиком »
Просмотров: 5973 | Комментариев: 9

Преобразование строки в число

10.11.2008 | Категория: Образ мышления: Assembler | Автор: ManHunter
Для конвертирования строки в число я использую две функции. Первая предназначена для конвертирования строки десятичных цифр в число:
  1. ;----------------------------------------------------------
  2. ; На входе: указатель на строку
  3. ; На выходе: EAX = число или 0 если не получилось
  4. ;----------------------------------------------------------
  5. proc    str2dec lpStr:dword
  6.         push    ebx edx esi
  7.  
  8.         xor     eax,eax
  9.         mov     esi,[lpStr]
  10. .str2dec_loop:
  11.         movsx   ebx,byte [esi]
  12.         sub     bl,'0'
  13.         ; Для системы счисления с другим основанием замените следующую
  14.         ; строчку на cmp bl,основание_системы
  15.         cmp     bl,10
  16.         jnb     .str2dec_ret
  17.         ; Для системы счисления с другим основанием замените следующую
  18.         ; строчку на imul eax,основание_системы
  19.         imul    eax,10
  20.         add     eax,ebx
  21.         inc     esi
  22.         jmp     .str2dec_loop
  23.  
  24. .str2dec_ret:
  25.         pop     esi edx ebx
  26.         ret
  27. endp
Вторая функция похожа, но обрабатывает шестнадцатеричные цифры:

Читать статью целиком »
Просмотров: 16974 | Комментариев: 5

Наверх
Powered by PCL's Speckled Band Engine 0.2 RC3
© ManHunter / PCL, 2008-2025
При использовании материалов ссылка на сайт обязательна
Время генерации: 0.1 сек. / MySQL: 3 (0.0048 сек.) / Память: 4.5 Mb
Наверх