Быстрый поиск
Введите фрагмент названия статьи для поиска
Вывод 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
Читать статью целиком »
Просмотров: 10056 | Комментариев: 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 записано реальное количество миллисекунд,
- ; прошедшее с момента старта системы
- ...
Читать статью целиком »
Просмотров: 6228 | Комментариев: 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
Читать статью целиком »
Просмотров: 7184 | Комментариев: 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
Читать статью целиком »
Просмотров: 5964 | Комментариев: 5
Перетаскивание окна за любое место
13.09.2008 | Категория: Образ мышления: Assembler | Автор: ManHunter
Перетаскивание окна за любое место, а не только за заголовок, реализуется очень просто, но смотрится очень эффектно. Тем более, что окно может быть вообще без заголовка. Для этого в обработчик окна надо добавить следующий код.Code (Assembler) : Убрать нумерацию
- ; Процедура обработчика окна
- proc DialogProc hwnddlg,msg,wparam,lparam
- ......
- ; Нажата левая кнопка мышки на окне?
- cmp [msg], WM_LBUTTONDOWN
- je drag_window
- ......
- drag_window:
- ; Освободить захват мыши окном в текущем потоке и
- ; восстановить обычную обработку ввода данных от мыши
- invoke ReleaseCapture
- ; Перенаправить сообщение передвижения мышью SC_MOVE на заголовок окна
- ; 61458 = SC_MOVE or HTCAPTION, в FASM по умолчанию не определено,
- ; поэтому сразу задается числовым значением
- invoke SendMessage,[hwnddlg],WM_SYSCOMMAND,61458,0
- ......
Читать статью целиком »
Просмотров: 7451 | Комментариев: 6