
Образ мышления: Assembler
То, что не удается запрограммировать на Ассемблере, приходится паять
Образ мышления: Assembler - RSS-канал
Образ мышления: Assembler - Карта сайта

Создание прозрачных окон в Windows
29.10.2008 | Категория: Образ мышления: Assembler | Автор: ManHunter
Еще один простой в реализации, но красивый эффект для ваших программ - прозрачные диалоговые окна. Для этого надо, чтобы диалоговое окно было прописано в ресурсах или создавалось с расширенным стилем WS_EX_LAYERED, а при его инициализации вызывалась функция SetLayeredWindowAttributes. Значение коэффициента прозрачности может быть от 0 (полностью прозрачное окно) до 255 (непрозрачное окно). Рекомендуется значение 240-245, при этом эффект прозрачности уже заметен, а содержимое окна еще легко читается и не сливается с перекрываемыми окнами. Этой же функцией можно динамически менять прозрачность уже созданного окна, например чтобы создать эффект его плавного появления или исчезновения.Code (Assembler) : Убрать нумерацию
- ; Сегмент кода
- section '.code' code readable executable
- ...
- ; Процедура обработчика окна
- proc DialogProc hwnddlg,msg,wparam,lparam
- ...
- ; Инициализация окна?
- cmp [msg], WM_INITDIALOG
- je wminitdialog
- ; Закрытие окна?
- cmp [msg], WM_CLOSE
- je wmclose
- ...
- wminitdialog:
- ; Установить первоначальную прозрачность окна 245
- invoke SetLayeredWindowAttributes, [hwnddlg], 0, 245, LWA_ALPHA
- ...
- wmclose:
- ; Плавное исчезновение окна при его закрытии
- mov ecx,245
- fade_dialog:
- push ecx
- ; Установка нового атрибта прозрачности
- invoke SetLayeredWindowAttributes, [hwnddlg], 0, ecx, LWA_ALPHA
- ; Небольшая пауза
- invoke Sleep,2
- pop ecx
- loop fade_dialog
- ...
- ; Секция ресурсов
- section '.rsrc' resource data readable
- ; Описание диалогового окна в ресурсах.
- ; В расширенных стилях должен быть прописан атрибут "WS_EX_LAYERED"
- dialog demo, 'Demo', 70, 70, 190, 175,\
- WS_CAPTION + WS_POPUP + WS_SYSMENU + DS_MODALFRAME,\
- WS_EX_LAYERED
- ...
Читать статью целиком »
Просмотров: 11406 | Комментариев: 4

Вывод QWORD в виде десятичного числа
05.10.2008 | Категория: Образ мышления: Assembler | Автор: ManHunter
Для преобразования и форматированного вывода 32-битных значений в ассемблере используется стандартная API-функция wsprintf, но она бесполезна при работе с большими числами, например QWORD (64 бита). Значит обойдемся совсем без использования API.Code (Assembler) : Убрать нумерацию
- ;---------------------------------------------------
- ; Преобразование QWORD в десятичное число
- ; Параметры вызова:
- ; dwHigh - Старшее двойное слово
- ; dwLow - Младшее двойное слово
- ; lpBuff - указатель на буфер-приемник
- ;---------------------------------------------------
- proc bignum dwHigh:DWORD, dwLow:DWORD, lpBuff:DWORD
- pushad ; Сохранить все регистры
- mov eax,[dwLow] ; Младшее двойное слово
- mov edx,[dwHigh] ; Старшее двойное слово
- mov edi,[lpBuff] ; Указатель на буфер-приемник
- xchg esi,edx ; Сохранить старший dword
- mov ebx,10 ; Основание системы счисления
- xor ecx,ecx ; Счетчик десятичных цифр
- .bignum_1:
- xchg eax,esi ; Расчитать десятичную цифру
- xor edx,edx
- div ebx
- xchg esi,eax
- div ebx
- or dl,'0' ; Преобразовать результат в символ цифры
- push edx ; Сохранить цифру в стеке
- inc ecx ; Увеличить счетчик цифр
- or eax,eax ; Все преобразовали?
- jnz .bignum_1
- .bignum_2:
- pop eax ; Записать все цифры из стека в буфер
- stosb
- loop .bignum_2
- xor eax,eax ; Признак окончания строки
- stosb
- popad ; Восстановить все регистры
- ret ; Ворзврат из процедуры
- endp
Читать статью целиком »
Просмотров: 10189 | Комментариев: 4

Время непрерывной работы (Uptime) Windows
01.10.2008 | Категория: Образ мышления: Assembler | Автор: ManHunter
Для получения времени непрерывной работы системы обычно используется функция API GetTickCount. Она возвращает количество миллисекунд, прошедших с момента последнего старта системы. Проблема в том, что счетчик имеет тип dword, и по прошествии примерно 50 дней (49,7 если быть точным) достигает предельного значения и обнуляется. Конечно, продержать систему без перезагрузки почти два месяца трудно, но не значит что невозможно. Поэтому для получения гарантированно точного времени работы системы воспользуемся функцией NtQuerySystemInformation. Достаточно долго эта функция относилась к разряду недокументированных, теперь же на MSDN по ней имеется описание с примечанием, что ее использование в прикладных программах все равно нежелательно.Code (Assembler) : Убрать нумерацию
- ; Сегмент данных
- section '.data' data readable writeable
- ; По умолчанию структура в FASM не определена, сделаем это самостоятельно
- ; Для получения необходимой информации нужны только два первых значения
- struct SYSTEM_TIME_INFORMATION
- liKeBootTime dq ? ; Время старта системы
- liKeSystemTime dq ? ; Текущее время
- liExpTimeZoneBias dq ?
- uCurrentTimeZoneId dd ?
- dwReserved dw ?
- ends
- SystemTime SYSTEM_TIME_INFORMATION ; Наша структура с данными
- ; Константа нужного класса информации тоже не определена, сделаем это сами
- GET_SYSTEM_TIME_INFORMATION = 3
- ; Сегмент кода
- section '.code' code readable executable
- ...
- invoke NtQuerySystemInformation, GET_SYSTEM_TIME_INFORMATION,\
- SystemTime, sizeof.SYSTEM_TIME_INFORMATION, 0
- ; Записать в регистры EDX:EAX текущее время в миллисекундах
- mov eax, dword [SystemTime.liKeSystemTime]
- mov edx, dword [SystemTime.liKeSystemTime+4]
- ; Вычесть время старта системы
- sub eax, dword [SystemTime.liKeBootTime]
- sbb edx, dword [SystemTime.liKeBootTime+4]
- ; Теперь в регистры EDX:EAX записано реальное количество миллисекунд,
- ; прошедшее с момента старта системы
- ...
Читать статью целиком »
Просмотров: 6328 | Комментариев: 1

Поиск строки в памяти с использованием маски
29.09.2008 | Категория: Образ мышления: Assembler | Автор: ManHunter
Для поиска произвольной строки в блоке памяти с использованием бинарной маски я написал следующую процедуру:Code (Assembler) : Убрать нумерацию
- ; ---------------------------------------------
- ; Процедура поиска строки в блоке памяти
- ; (C) ManHunter / PCL
- ; ---------------------------------------------
- ; SRCdata - блок памяти в котором выполняется поиск
- ; SRCsize - размер блока в котором выполняется поиск
- ; PTRdata - строка для поиска
- ; PTRsize - длина строки для поиска
- ; MSKdata - бинарная маска для поиска или 0 если не используется
- ;
- ; Возврат: EAX = offset найденной строки
- ; EAX = -1 если ничего не найдено
- ; ---------------------------------------------
- proc scanmem SRCdata:dword, SRCsize:dword, PTRdata:dword,\
- PTRsize:dword, MSKdata:dword
- push esi edi ebx ecx edx
- ; Длина паттерна больше длины данных?
- mov eax,[PTRsize]
- cmp eax,[SRCsize]
- ; Да, возврат -1
- ja .scanmem_not_found
- mov esi,[SRCdata]
- mov edi,[PTRdata]
- mov edx,[MSKdata]
- mov ebx,esi
- add ebx,[SRCsize]
- sub ebx,[PTRsize]
- .scanmem_loop:
- xor ecx,ecx
- .scanmem_test_char:
- or edx,edx
- jz .scanmem_no_mask
- cmp byte [edx+ecx],0
- jz .scanmem_char_equal
- .scanmem_no_mask:
- mov al,[esi+ecx]
- cmp al,[edi+ecx]
- jne .scanmem_next_pattern
- .scanmem_char_equal:
- inc ecx
- cmp ecx,[PTRsize]
- jb .scanmem_test_char
- jmp .scanmem_found
- .scanmem_next_pattern:
- inc esi
- cmp esi,ebx
- jbe .scanmem_loop
- .scanmem_not_found:
- ; Строка не найдена
- mov eax,-1
- jmp .scanmem_ret
- .scanmem_found:
- ; Строка найдена
- mov eax,esi
- .scanmem_ret:
- pop edx ecx ebx edi esi
- ret
- endp
Читать статью целиком »
Просмотров: 7304 | Комментариев: 5

Вывод лога на Ассемблере
19.09.2008 | Категория: Образ мышления: Assembler | Автор: ManHunter
Если при работе вашей программы требуется вывод лога неопределенной длины, то это удобно делать в многострочном поле Edit. Преимущества такого способа налицо: можно мышкой выделить и скопировать любой кусок текста, средствами API получить весь текст целиком и сохранить в файл, быстро очистить окно лога и многое другое. Удобно делать все, кроме главного: добавление новых строчек в лог. Конечно, можно получать текст, в памяти добавлять к нему новые строчки и вставлять обратно. Но это долго, неудобно и требует дополнительных ресурсов, а для очень больших логов и вовсе неприемлемо. Поэтому воспользуемся следующей функцией:Code (Assembler) : Убрать нумерацию
- ;---------------------------------------------
- ; procedure AddLog
- ; void AddLog(hWnd:dword,CtrlID:dword,pStr:&string)
- ;---------------------------------------------
- proc AddLog hWnd:dword,CtrlID:dword,pStr:dword
- push eax
- invoke GetDlgItem,[hWnd],[CtrlID]
- or eax,eax
- jz .AddLog_1
- mov [CtrlID],eax
- invoke SendMessage,[CtrlID],EM_GETLINECOUNT,0,0
- dec eax
- invoke SendMessage,[CtrlID],EM_LINEINDEX,eax,0
- invoke SendMessage,[CtrlID],EM_SETSEL,eax,eax
- invoke SendMessage,[CtrlID],EM_REPLACESEL,FALSE,[pStr]
- .AddLog_1:
- pop eax
- ret
- endp
Читать статью целиком »
Просмотров: 6074 | Комментариев: 5
