Blog. Just Blog

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

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

Обработка подключения и отключения съемного накопителя

18.04.2011 | Категория: Образ мышления: Assembler | Автор: ManHunter
С расширением рынка переносных устройств и USB-накопителей становится актуальной задача по обработке их взаимодействия с компьютером. Сегодня разберем обработку подключения и отключения съемных накопителей, таких как Flash-диски, карты памяти и USB-диски. Начинаем с теории. При подключении или отключении съемного накопителя система посылает всем окнам (через глобальный хэндл HWND_BROADCAST) сообщение WM_DEVICECHANGE. Но это сообщение всего лишь о самом факте изменения состояния съемного накопителя, а более подробные значения содержатся в параметрах lParam и wParam этого сообщения. В wParam приходит расшифровка произошедшего события: подключение, отключение, изменения состояния, отмена отключения и т.п. Нас пока интересует только два: DBT_DEVICEARRIVAL - подключение сменного накопителя и DBT_DEVICEREMOVECOMPLETE - извлечение накопителя. Основной обработчик событий приложения ничем не отличается от обычных обработчиков. Нам также понадобятся несколько констант, которые по умолчанию не определены в FASM:
  1. DBT_DEVICEARRIVAL        = 0x8000
  2. DBT_DEVICEREMOVECOMPLETE = 0x8004
  3.  
  4. DBT_DEVTYP_VOLUME        = 0x00000002
И, собственно, сам обработчик. Я оставил только нужные фрагменты кода:
  1. proc DialogProc hwnddlg,msg,wparam,lparam
  2.         push    ebx esi edi
  3.         ...
  4.         ; Пришло сообщение об изменении состояния съемного накопителя
  5.         cmp     [msg],WM_DEVICECHANGE
  6.         je      update_usb
  7.         ...
  8. update_usb:
  9.         ; Устройство подключено?
  10.         cmp     [wparam],DBT_DEVICEARRIVAL
  11.         je      usb_connected
  12.  
  13.         ; Устройство извлечено?
  14.         cmp     [wparam],DBT_DEVICEREMOVECOMPLETE
  15.         je      usb_disconnected
  16.  
  17.         jmp     processed
  18.  
  19. usb_connected:
  20.         ; Обработка подключения устройства
  21.         ...
  22.         jmp     processed
  23.  
  24. usb_disconnected:
  25.         ; Обработка отключения устройства
  26.         ...
  27.         jmp     processed
  28.         ...
  29. processed:
  30.         mov     eax,1
  31. finish:
  32.         pop     edi esi ebx
  33.         ret
  34. endp
Для полноты картины осталось узнать, какой именно диск был подключен или извлечен. В параметре lParam сообщения WM_DEVICECHANGE передается указатель на структуру, которая содержит подробную информацию о случившемся событии. FASM про нее тоже ничего не знает, поэтому придется и ее описать самостоятельно.

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

Splash-окно при загрузке программы

31.03.2011 | Категория: Образ мышления: Assembler | Автор: ManHunter
При запуске некоторых приложений иногда требуется выполнить какие-нибудь ресурсоемкие или продолжительные по времени действия, например, загрузка дополнительных модулей, сбор информации о системе, распаковка файлов данных и т.п. Часто во время таких процессов открывается так называемое splash-окно (его также называют "сплэш-окно" или сокращенно "сплэш"), то есть модальное окно без заголовка, расположенное по центру экрана, обычно с логотипом и названием программы. Также в нем меняющейся строкой отображается текущее действие программы, и, иногда, полоса прогресса выполнения. Таким образом пользователя как бы уведомляют, что программа не зависла при запуске, а просто выполняет нужные ей действия и надо немного подождать. После появления главного окна программы сплэш закрывается. Попробуем сделать что-нибудь подобное на Ассемблере.

Сперва нарисуем само окно. Оно должно быть без заголовка, модальное, можно разместить на нем картинку-логотип. Для большего эффекта добавим на это окно прогрессбар и текстовое поле для отображения состояния загрузки.
  1. ; Стиль прогрессбара - непрерывный бегунок. В FASM значение не определено,
  2. ; сделаем это самостоятельно
  3. PBS_MARQUEE = 8
  4.  
  5. dialog demonstration,' Splash Demo',0, 0, 150, 60,\
  6.     WS_POPUP+DS_CENTER+DS_SYSMODAL+WS_BORDER, WS_EX_TOOLWINDOW,0,'Arial',10
  7.   dialogitem 'STATIC',1, 1, 0, 0, 138, 38 ,WS_VISIBLE+SS_BITMAP
  8.   dialogitem 'STATIC','Loading...',ID_TEXT, 0, 34, 150, 8 ,WS_VISIBLE+SS_CENTER
  9.   dialogitem 'msctls_progress32', '', IDC_PROGRESS, 3, 47, 145, 10,\
  10.     WS_VISIBLE+PBS_MARQUEE
  11.   dialogitem 'BUTTON','',IDCANCEL, 0, 0, 0, 0, 0
  12. enddialog
Несколько комментариев к коду. Прогрессбар задается в ресурсах как элемент диалогового окна msctls_progress32 со стилем PBS_MARQUEE, то есть он будет непрерывно двигаться. Если требуется указание более точного процента выполнения загрузки, то придется обратиться к документации. Скрытая кнопка EXIT предназначена для того, чтобы splash-окно можно было закрыть при помощи клавиши Esc. Как правило, разработчики пренебрегают возможностью закрывать сплэш по желанию пользователя, и посреди экрана висит уродливое окно, которое нельзя ни закрыть, ни передвинуть, пока приложение не загрузится. Никогда так не делайте! Также обратите внимание, чтобы заработал такой прогрессбар, должна быть вызвана функция InitCommonControls, а исполняемый файл должен содержать соответствующий манифест.

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

"FASM и UPX: созданы друг для друга"

25.03.2011 | Категория: Образ мышления: Assembler | Автор: ManHunter
Сразу скажу, утро и кофе к этой статье отношения не имеют, все необычные решения приходят ко мне обычно по ночам. Однажды я экспериментировал с FASM, и обнаружил один интересный момент. Ниже приведен ассемблерный листинг самой простейшей программы, она выводит на экран сообщение и сразу же завершает работу, вроде бы ничего необычного.
  1. section '.code' code readable executable
  2.  
  3.   start:
  4.         ; Вывести окно сообщения и выйти из программы
  5.         invoke  MessageBox, NULL, szMess, szTitle, MB_OK
  6.         invoke  ExitProcess,0
  7.  
  8.         ; Куча пустого места, чтобы можно было упаковать файл
  9.         rd      1000h
  10.  
  11. szTitle db      'Title',0
  12. szMess  db      'Hello, UPX ;)',0
  13.  
  14. ;---------------------------------------------
  15.  
  16. section '.idata' import data readable writeable
  17.  
  18. ; Обратите внмание, user32.dll прописан дважды
  19. library kernel32,'kernel32.dll',\
  20.         user32,'user32.dll',\
  21.         user32,'user32.dll'
  22.  
  23. include 'apia\kernel32.inc'
  24. include 'apia\user32.inc'
Но обратите внимание, что в секции импорта user32.dll прописан дважды. Это и есть та самая фишка, которую я случайно обнаружил. Блок нулевых байт в середине нужен, чтобы файл получился большой и его можно было упаковать. В реальных приложениях, скорее всего, такие избыточные данные не понадобятся.

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

Управление лотком CD-ROM на Ассемблере

06.02.2011 | Категория: Образ мышления: Assembler | Автор: ManHunter
Открывать и закрывать лоток CD-ROM можно программными способами. Это может оказаться полезным в случаях, когда системный блок стоит в труднодоступном месте или по каким-либо иным причинам нет возможности управлять им при помощи механической кнопки. Также я читал истории, когда на лоток CD-ROM возлагались полезные функции, например, при выдвижении он замыкал контакты питания и отправлял сервер в перезагрузку, а администратор таким образом удаленно управлял им. Так что программное управление лотком CD-ROM имеет место быть, и наша задача научиться его делать. Чаще всего в разных интернетах описывается способ управления при помощи MCI (Media Control Interface). Кстати, именно этот способ приводится в качестве одного из примеров программ в пакете FASM.
  1.         ...
  2.         ; Открыть лоток CD-ROM
  3.         invoke  mciSendString,cmd_open,0,0,0
  4.         invoke  mciSendString,cmd_eject,0,0,0
  5.         invoke  mciSendString,cmd_close,0,0,0
  6.         ...
  7.         ; Закрыть лоток CD-ROM
  8.         invoke  mciSendString,cmd_open,0,0,0
  9.         invoke  mciSendString,cmd_load,0,0,0
  10.         invoke  mciSendString,cmd_close,0,0,0
  11.         ...
  12. cmd_open   db 'open cdaudio',0
  13. cmd_eject  db 'set cdaudio door open',0
  14. cmd_load   db 'set cdaudio door closed',0
  15. cmd_close  db 'close cdaudio',0
У данного метода есть недостатки. Главный заключается в том, что при наличии в системе нескольких приводов CD-ROM нет возможности указать, лоток которого из них необходимо выдвигать, всегда открывается первый по счету. Второй существенный недостаток - некоторые антивирусы считают наличие таких функций в программах потенциально опасными. Видимо из-за того, что иногда несанкционированное открытие лотка CD-ROM используется в различных программах-шутках для окошмаривания доверчивых пользователей.

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

Проверка баланса скобок на Ассемблере

28.01.2011 | Категория: Образ мышления: Assembler | Автор: ManHunter
Есть такая классическая задача по программированию: проверка правильности расстановки скобок в строке, или иначе проверка баланса скобок. Суть задачи заключается в том, что есть произвольное математическое выражение, записанное в строку, в этом выражении используется три вида скобок "( )", "[ ]" и "{ }", последовательность и вложенность может быть любая. Требуется проверить, все ли скобки закрыты, соответствует ли каждая закрывающая скобка открывающей и нет ли лишних закрывающих скобок. В разных интернетах есть решения на различных языках программирования, я решил добавить свое решение на Ассемблере, тем более, что он идеально подходит для реализации этого алгоритма.

Решение заключается в том, что мы двигаемся по строке с самого начала, перебирая все символы по одному. Если символ является открывающей скобкой любого типа, то мы помещаем его в стек. Если символ является закрывающей скобкой, то берем из стека последнюю сохраненную открывающую скобку и проверяем на соответствие. Если не совпадают - ошибка несоответствия скобок, если стек пустой, то ошибка лишней закрывающей скобки. Если конец строки достигнут, но стек не пустой, то ошибка незакрытых скобок. Как видите, решение целиком построено на работе со стеком, а Ассемблер предоставляет для этого все возможности. Переходим к программированию.
  1. ;------------------------------------------------------------------------
  2. ; Функция проверки правильности расстановки скобок в выражении
  3. ; На входе: указатель на строку ASCIIZ
  4. ; На выходе: EAX - результат проверки выражения
  5. ;    0 - скобки расставлены правильно
  6. ;    1 - ОШИБКА: скобки не совпадают
  7. ;    2 - ОШИБКА: закрывающая скобка без открывающей
  8. ;    3 - ОШИБКА: открывающая скобка без закрывающей
  9. ;------------------------------------------------------------------------
  10. proc    CheckBrackets str:DWORD
  11.         local res:DWORD ; Результат
  12.  
  13.         pusha                   ; Сохранить все регистры
  14.  
  15.         mov     esi,[str]       ; Указатель на строку
  16.         cld
  17.         xor     ecx,ecx         ; Глубина стека
  18.         mov     [res],0         ; Результат проверки
  19.  
  20. .scan_expr:
  21.         lodsb                   ; Прочитать символ из строки
  22.         or      al,al           ; Конец строки достигнут?
  23.         jz      .finish
  24.  
  25.         ; Проверить открывающие скобки
  26.         cmp     al,'['
  27.         je      .push_bracket
  28.         cmp     al,'('
  29.         je      .push_bracket
  30.         cmp     al,'{'
  31.         je      .push_bracket
  32.  
  33.         ; Проверить закрывающие скобки
  34.         cmp     al,']'
  35.         je      .pop_bracket
  36.         cmp     al,')'
  37.         je      .pop_bracket
  38.         cmp     al,'}'
  39.         je      .pop_bracket
  40.  
  41.         jmp     .scan_expr      ; Следующий символ
  42.  
  43.         ; Занести скобку в стек
  44. .push_bracket:
  45.         inc     ecx             ; Увеличить счетчик
  46.         movzx   eax,al          ; Записать скобку в стек
  47.         push    eax
  48.         jmp     .scan_expr      ; Следующий символ
  49.  
  50.         ; Извлечь скобку из стека
  51. .pop_bracket:
  52.         or      ecx,ecx         ; В стеке ничего нет?
  53.         jne     @f
  54.  
  55.         ; ОШИБКА: закрывающая скобка без открывающей
  56.         mov     [res],2
  57.         jmp     .finish
  58. @@:
  59.         dec     ecx             ; Уменьшить счетчик
  60.         pop     ebx             ; Извлечь из стека скобку
  61.  
  62.         ; Проверить закрывающие скобки
  63.         cmp     bl,'['
  64.         jne     @f
  65.  
  66.         cmp     al,']'          ; Скобки совпадают?
  67.         je      .scan_expr      ; Да, следующий символ
  68. @@:
  69.         cmp     bl,'('
  70.         jne     @f
  71.  
  72.         cmp     al,')'          ; Скобки совпадают?
  73.         je      .scan_expr      ; Да, следующий символ
  74. @@:
  75.         cmp     bl,'{'
  76.         jne     @f
  77.  
  78.         cmp     al,'}'          ; Скобки совпадают?
  79.         je      .scan_expr      ; Да, следующий символ
  80. @@:
  81.         ; ОШИБКА: скобки не совпадают
  82.         mov     [res],1
  83.         or      ecx,ecx         ; В стеке пусто?
  84.         jz      .exit           ; Да, просто на выход
  85.         jmp     .clean_stack    ; Надо почистить стек
  86. .finish:
  87.         or      ecx,ecx         ; Все проверили и в стеке пусто?
  88.         jz      .exit           ; Да, скобки расставлены правильно
  89.  
  90.         ; ОШИБКА: открывающая скобка без закрывающей
  91.         mov     [res],3
  92.  
  93.         ; Почистить стек от оставшихся скобок
  94. .clean_stack:
  95.         pop     eax
  96.         loop    .clean_stack
  97. .exit:
  98.         popa                    ; Восстановить все регистры
  99.         mov     eax,[res]
  100.  
  101.         ret
  102. endp
Текст функции проверки подробно прокомментирован, так что в дополнительных пояснениях не нуждается. Тем более, что алгоритм был расписан словами выше. Где это можно использовать? Кроме различных калькуляторов подобные решения можно применять для валидации xml-подобных документов, при проверке синтаксиса каких-либо скриптов и т.п., так что главное уяснить принцип.

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

01 ... 61 62 63 64 65 66 67 ... 75
Наверх
Powered by PCL's Speckled Band Engine 0.2 RC3
© ManHunter / PCL, 2008-2025
При использовании материалов ссылка на сайт обязательна
Время генерации: 0.11 сек. / MySQL: 3 (0.016 сек.) / Память: 4.5 Mb
Наверх