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

Преобразование строки в вещественное число на Ассемблере
31.05.2012 | Категория: Образ мышления: Assembler | Автор: ManHunter
Про преобразование строки в обычное число я уже писал, теперь задача посложнее - надо преобразовать строку в вещественное число с плавающей запятой (float). Для этого я написал вот такую функцию преобразования:Code (Assembler) : Убрать нумерацию
- ;------------------------------------------------------------
- ; Функция преобразования строки в вещественное число
- ; by ManHunter / PCL
- ; http://www.manhunter.ru
- ;
- ; Параметры:
- ; lpStr - указатель на исходную строку в формате ASCIIZ
- ; lpResult - указатель на переменную-приемник значения
- ; На выходе:
- ; EAX = 1 - строка успешно преобразована
- ; EAX = 0 - строка не может быть преобразована в число
- ;
- ; Примечание: переменная-приемник может иметь размер DWORD
- ; или QWORD, в зависимости от этого должна изменяться и
- ; функция (см. комментарии в конце кода). По умолчанию
- ; считается, что переменная имеет размер DWORD
- ;------------------------------------------------------------
- proc string2float lpStr:DWORD, lpResult:DWORD
- ; Локальные переменные
- locals
- dot dd ? ; Указатель на дробную часть
- exp dd ? ; Указатель на экспоненту
- digit dd ? ; Цифра
- endl
- pusha
- ; Проверка строки на валидность
- mov [digit],1
- mov [exp],0
- mov [dot],0
- mov esi,[lpStr]
- ; Минус или плюс может быть только в начале
- cmp byte [esi],'-'
- je @f
- cmp byte [esi],'+'
- jne .loc_chk_loop
- @@:
- inc esi
- ; После знака не может быть нуля
- cmp byte [esi],0
- je .loc_chk_error
- .loc_chk_loop:
- ; В строке должны быть цифр, экспонента и не более одной точки
- lodsb
- or al,al
- jz .loc_chk_complete
- cmp al,'e'
- je .loc_chk_exp
- cmp al,'E'
- je .loc_chk_exp
- cmp al,'.'
- je .loc_chk_dot
- cmp al,'0'
- jb .loc_chk_error
- cmp al,'9'
- ja .loc_chk_error
- jmp .loc_chk_loop
- .loc_chk_dot:
- ; Точка в строке уже есть?
- cmp [dot],0
- ; Строка имеет некорректный формат
- jne .loc_chk_error
- ; Экспонента уже есть?
- cmp [exp],0
- ; Строка имеет некорректный формат
- jne .loc_chk_error
- ; Указатель на дробную часть
- mov [dot],esi
- jmp .loc_chk_loop
- .loc_chk_exp:
- ; Экспонента уже есть?
- cmp [exp],0
- ; Строка имеет некорректный формат
- jne .loc_chk_error
- ; Указатель на начало экспоненты
- mov [exp],esi
- ; Сразу после экспоненты не может быть нуля
- cmp byte [esi],0
- je .loc_chk_error
- ; После экспоненты может быть знак
- cmp byte [esi],'-'
- je @f
- cmp byte [esi],'+'
- jne .loc_chk_loop
- @@:
- inc esi
- ; Сразу после минуса не может быть нуля
- cmp byte [esi],0
- je .loc_chk_error
- ; Проверить следующий символ
- jmp .loc_chk_loop
- .loc_chk_error:
- ; Строка не является числом
- mov [digit],0
- jmp .loc_ret
- .loc_chk_complete:
- ; Инициализация сопроцессора
- finit
- ; Начальное значение числа
- fldz
- ; Множитель и делитель
- mov [digit],10
- fild dword [digit]
- ; Запись значений до запятой
- mov esi,[lpStr]
- ; В начале строки минус?
- cmp byte [esi],'-'
- je @f
- cmp byte [esi],'+'
- jne .loc_before_dot
- @@:
- inc esi
- ; Преобразование числа до запятой
- .loc_before_dot:
- lodsb
- ; Конец строки?
- or al,al
- jz .loc_complete
- cmp al,'.'
- je .loc_complete_before_dot
- cmp al,'e'
- je .loc_exp
- cmp al,'E'
- je .loc_exp
- ; Очередная цифра
- sub al,'0'
- movzx eax,al
- mov [digit],eax
- ; Записать
- fild dword [digit]
- fxch st2
- fmul st0,st1
- fxch st2
- fadd st2,st0
- ffree st0 ; Почистить стек
- fincstp
- jmp .loc_before_dot
- ; Преобразование дробной части числа
- .loc_complete_before_dot:
- ; Дробная часть есть?
- cmp [dot],0
- je .loc_complete_after_dot
- ; Экспонента есть?
- cmp [exp],0
- je @f
- ; Указатель на начало экспоненты
- mov esi,[exp]
- jmp .loc_start_after_dot
- @@:
- ; Иначе перенести указатель на конец строки
- xor ecx,ecx
- dec ecx
- xor eax,eax
- mov edi,esi
- repne scasb
- mov esi,edi
- .loc_start_after_dot:
- std
- dec esi
- dec esi
- ; Дробная часть
- fldz
- fxch st1
- .loc_after_dot:
- lodsb
- ; Конец дробной части?
- cmp al,'.'
- je .loc_complete_after_dot
- ; Очередная цифра
- sub al,'0'
- movzx eax,al
- mov [digit],eax
- ; Записать
- fild dword [digit]
- fadd st2,st0
- fxch st2
- fdiv st0,st1
- fxch st2
- ffree st0 ; Почистить стек
- fincstp
- jmp .loc_after_dot
- .loc_complete_after_dot:
- ; Сбросить флаг направления
- cld
- ffree st0 ; Почистить стек
- fincstp
- ; Сложить дробную и целую часть
- fadd st1,st0
- .loc_exp:
- ; Экспонента есть?
- cmp [exp],0
- je .loc_complete
- ; Получить значение экспоненты
- xor ecx,ecx
- mov esi,[exp]
- ; В начале строки минус?
- cmp byte [esi],'-'
- je @f
- cmp byte [esi],'+'
- jne .loc_start_exp
- @@:
- inc esi
- .loc_start_exp:
- lodsb
- or al,al
- jz .loc_end_exp
- sub al,'0'
- movzx eax,al
- imul ecx,10
- add ecx,eax
- jmp .loc_start_exp
- .loc_end_exp:
- or ecx,ecx
- jz .loc_complete
- ffree st0 ; Почистить стек
- fincstp
- mov [digit],10
- fild dword [digit]
- ; Делить или умножать?
- mov esi,[exp]
- cmp byte [esi],'-'
- je .loc_exp_divide
- .loc_exp_multiple:
- fmul st1,st0
- loop .loc_exp_multiple
- jmp .loc_complete
- .loc_exp_divide:
- fdiv st1,st0
- loop .loc_exp_divide
- .loc_complete:
- ffree st0 ; Почистить стек
- fincstp
- ; В начале строки минус?
- mov esi,[lpStr]
- cmp byte [esi],'-'
- jne @f
- ; Изменить знак числа
- fchs
- @@:
- ; Записать значение в ячейку памяти
- mov eax,[lpResult]
- ; Если требуется повышенная точность, то приемник
- ; должен иметь размер QWORD, а следующую команду
- ; надо заменить на fstp qword [eax]
- fstp dword [eax]
- ; Успешное преобразование
- mov [digit],1
- .loc_ret:
- popa
- ; Результат преобразования
- mov eax,[digit]
- ret
- endp
Читать статью целиком »
Просмотров: 9268 | Комментариев: 13

Расчет хеша MD4 на Ассемблере
17.04.2012 | Категория: Образ мышления: Assembler | Автор: ManHunter
MD4 (Message Digest 4) - хеш-функция, разработанная профессором Рональдом Ривестом в 1990 году. Для произвольных входных данных функция MD4 генерирует 128-разрядный хеш. Функция MD4 является предшественником MD5 и до настоящего времени применяется в некоторых сетевых технологиях Windows. В реализации обоих алгоритмов очень много общего, поэтому точно так же в сегменте данных надо подготовить следующие массивы и переменные:Code (Assembler) : Убрать нумерацию
- ; Сегмент данных
- section '.data' data readable writeable
- ...
- ; Шаблоны функции wsprintf для перевода хеша в строковый вид,
- ; при необходимости можно оставить только какой-нибудь один
- szMD4Format1 db '%.8X%.8X%.8X%.8X',0 ; Для получения заглавных букв
- szMD4Format2 db '%.8x%.8x%.8x%.8x',0 ; Для маленьких букв в строке хеша
- stMD4Result:
- stdtA dd ? ; Переменные для получения и хранения
- stdtB dd ? ; результата хеширования
- stdtC dd ?
- stdtD dd ?
- stMD4Hash rb 33 ; Буфер для строки хеша в формате ASCIIZ
Читать статью целиком »
Просмотров: 4389 | Комментариев: 2

Замена подстроки в строке на Ассемблере
28.03.2012 | Категория: Образ мышления: Assembler | Автор: ManHunter
Во всех языках высокого уровня среди функций работы со строками присутствуют функции замены заданной подстроки в строке. В Ассемблере такой функции нет, как нет ее и среди функций стандартных библиотек. Замена подстроки на строку такой же длины обычно сложностей не составляет, так как ее можно выполнить прямо в исходной строке без выделения дополнительной памяти. Замена на строку произвольной длины, в том числе и пустую, будет посложнее. Для этого я написал следующую функцию.Code (Assembler) : Убрать нумерацию
- ;-----------------------------------------------------
- ; Функция замены подстроки в строке
- ;-----------------------------------------------------
- ; lpSrc - указатель на исходную строку
- ; lpDst - указатель на буфер для полученной строки
- ; lpPattern - указатель на заменяемую подстроку
- ; lpReplace - указатель на строку для замены
- ; dNum - количество замен (0 - заменить все)
- ;-----------------------------------------------------
- proc _replace lpSrc:DWORD, lpPattern:DWORD, lpReplace:DWORD,\
- lpDst:DWORD, dNum:DWORD
- pusha
- ; Указатель на буфер-приемник
- mov edx,[lpDst]
- ; Счетчик замен
- xor ebx,ebx
- ; Исходная строка не пустая?
- mov ecx,[lpSrc]
- cmp byte [ecx],0
- jz .loc_ret
- ; Заменяемая строка не пустая?
- mov eax,[lpPattern]
- cmp byte [eax],0
- jz .loc_copy_all
- .loc_scan:
- mov esi,ecx
- mov edi,[lpPattern]
- ; Исходная строка закончилась?
- cmp byte [esi],0
- je .loc_end_replace
- @@:
- ; Строки совпали с паттерном?
- cmp byte [edi],0
- je .loc_move_replace
- ; Символ совпадает с
- lodsb
- ; Заменять все вхождения?
- cmp [dNum],0
- je .loc_skip_counter
- ; Уже заменили нужное количество?
- cmp ebx,[dNum]
- je .loc_move_one_char
- .loc_skip_counter:
- cmp al,byte [edi]
- jne .loc_move_one_char
- inc edi
- jmp @b
- .loc_move_replace:
- ; Увеличить счетчик замен
- inc ebx
- mov ecx,esi
- ; Записать заменяющую строку
- mov esi,[lpReplace]
- mov edi,edx
- @@:
- lodsb
- or al,al
- jz .loc_scan
- stosb
- inc edx
- jmp @b
- .loc_move_one_char:
- ; Скопировать один символ
- mov al,byte [ecx]
- mov byte [edx],al
- inc edx
- inc ecx
- jmp .loc_scan
- .loc_end_replace:
- ; Записать финальный 0 в строку
- mov byte [edx],0
- jmp .loc_ret
- .loc_copy_all:
- ; Просто скопировать исходную строку
- mov esi,[lpSrc]
- mov edi,[lpDst]
- @@:
- lodsb
- stosb
- or al,al
- jnz @b
- .loc_ret:
- popa
- ret
- endp
Читать статью целиком »
Просмотров: 11662 | Комментариев: 8

Управление другим приложением из своей программы
12.02.2012 | Категория: Образ мышления: Assembler | Автор: ManHunter
Под управлением сторонним приложением я подразумеваю некие действия своей программы, эмулирующие действия живого человека. Например, нажатия на кнопки в диалоговых окнах. Попробуем сделать это на примере лоадера для популярного файлового менеджера Total Commander. Кто пользуется им, тот знает, что единственное различие между полной и незарегистрированной версией в том, что триалка при запуске показывает наг-скрин с предложением купить программу или нажать для продолжения одну из трех кнопок с цифрами. Конечно, кнопку можно нажать самостоятельно, но можно доверить это лоадеру.
Наг-скрин Total Commander
Чтобы работать с содержимым окна, сперва надо узнать его хэндл. Проще всего воспользоваться функцией FindWindow, указав в качестве параметра наименование класса наг-скрина. Его можно посмотреть при помощи моей программы WinDowzer или любой другой аналогичной программы. Противное окно имеет название класса TNASTYNAGSCREEN, первый шаг сделан. Теперь нам надо узнать хэндл нужной кнопки, для этого нужно изучить все связи родительских и дочерних объектов окна.
Читать статью целиком »
Просмотров: 10613 | Комментариев: 7

Принудительное обновление иконок в трее
12.01.2012 | Категория: Образ мышления: Assembler | Автор: ManHunter
В случае аварийного завершения или некорректной работы некоторых приложений, в системном трее могут оставаться "мертвые" иконки, которые уже не принадлежат ни одному запущенному процессу. Глюк хоть и не смертельный, но все равно неприятный. И основная проблема в том, что область трея никак не реагирует на внешние сообщения типа WM_REPAINT, и функции типа UpdateWindow и InvalidateRect. То есть автоматически обновить или перерисовать его, чтобы избавиться от "мертвых" иконок, не получится. Но такие иконки удаляются, если провести курсором мышки над ними. Значит единственный способ перерисовать иконки в трее - это сэмулировать движение мыши над окном трея. Как найти окно трея и его хэндл мы уже знаем, тут ничего нового. В сегменте данных те же значения:Code (Assembler) : Убрать нумерацию
- ; Сегмент данных
- section '.data' data readable writeable
- class1 db 'Shell_TrayWnd',0 ; Название класса окна трея
- class2 db 'TrayNotifyWnd',0 ; Название класса панели уведомлений
- class3 db 'SysPager',0 ; Трей
- class4 db 'ToolbarWindow32',0 ; Панель с иконками
- ToolbarHandle dd ? ; Хэндл окна трея
- ToolbarRect RECT ; Размер окна трея
Code (Assembler) : Убрать нумерацию
- ; Найти окно трея
- invoke FindWindow,class1,NULL
- or eax,eax
- jz exit_process
- ; Найти панель уведомлений
- invoke FindWindowEx,eax,NULL,class2,NULL
- or eax,eax
- jz exit_process
- ; Найти трей
- invoke FindWindowEx,eax,NULL,class3,NULL
- or eax,eax
- jz exit_process
- ; Найти панель иконок в трее
- invoke FindWindowEx,eax,NULL,class4,NULL
- or eax,eax
- jz exit_process
- ; Сохранить хэндл окна с иконками
- mov [ToolbarHandle],eax
Читать статью целиком »
Просмотров: 8958 | Комментариев: 21
