Blog. Just Blog

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

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

Задача на применение логических инструкций

16.12.2008 | Категория: Образ мышления: Assembler | Автор: ManHunter
Когда-то кому-то помогал с решением задачи на ассемблере, формулировка задания была такая:


Дан массив из 5 байт. Рассматривая его как массив из восьми 5-битных слов, посчитать количество слов с четным числом единиц в слове.


Алгоритм хитровывернутый, комментарии специально не прописывал, чтобы тупая и ленивая школота не смогла объяснить преподу, откуда взялось такое решение и как оно работает.
  1. ;---------------------------------------------------------------
  2. ; Задача на применение логических инструкций
  3. ;
  4. ; Дан массив из 5 байт. Рассматривая его как массив из восьми
  5. ; 5-битных слов, посчитать количество слов с четным числом
  6. ; единиц в слове.
  7. ;
  8. ; Решение: ManHunter / PCL
  9. ;---------------------------------------------------------------
  10.  
  11. format PE GUI 4.0
  12. entry start
  13.  
  14. include 'win32a.inc'
  15.  
  16. ;---------------------------------------------------------------
  17.  
  18. section '.data' data readable writeable
  19.  
  20. xbytes   db 00111000b ; Данные для задачки, взяты с потолка :)
  21.          db 11111110b
  22.          db 01010101b
  23.          db 00001001b
  24.          db 00000110b
  25.  
  26. mask     db 'Count: %i',13,10,13,10
  27.          db '%i%i%i%i%i - %i%i%i%i%i - %i%i%i%i%i - %i%i%i%i%i',13,10
  28.          db '%i%i%i%i%i - %i%i%i%i%i - %i%i%i%i%i - %i%i%i%i%i',13,10
  29.         db 0
  30.  
  31. title    db 'Solution',0
  32. tmp      rb 100
  33.  
  34. ;---------------------------------------------------------------
  35.  
  36. section '.code' code readable executable
  37. start:
  38.          mov     esi,xbytes+4
  39. loc_1:
  40.          lodsb
  41.          mov     ecx,8
  42. loc_2:
  43.          xor     edx,edx
  44.          test    al,00000001b
  45.          jz      loc_3
  46.          inc     edx
  47. loc_3:
  48.          push    edx
  49.          shr     al,1
  50.          loop    loc_2
  51.  
  52.          dec     esi
  53.          dec     esi
  54.          cmp     esi,xbytes
  55.          jnb     loc_1
  56.  
  57.          xor     eax,eax
  58.          xor     esi,esi
  59. loc_4:
  60.          xor     edi,edi
  61.          mov     ecx,5
  62. loc_5:
  63.          add     edi,[esp+eax*4]
  64.          inc     eax
  65.          loop    loc_5
  66.  
  67.          test    edi,edi
  68.          jz      loc_6
  69.          test    edi,1
  70.          jnz     loc_6
  71.          inc     esi
  72. loc_6:
  73.          cmp     eax,40
  74.          jb      loc_4
  75.  
  76.          invoke  wsprintf,tmp,mask,esi
  77.          add     esp,12+(8*5*4)
  78.  
  79.          invoke  MessageBox,HWND_DESKTOP,tmp,title,MB_OK
  80.          invoke  ExitProcess,0
  81.  
  82. ;---------------------------------------------------------------
  83.  
  84. section '.idata' import data readable writeable
  85.  
  86. library kernel32,"KERNEL32.DLL",\
  87.          user32,"USER32.DLL"
  88.  
  89. include "apia\kernel32.inc"
  90. include "apia\user32.inc"
Исходник и скомпилированный файл прилагаются.

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

Обработка перетаскивания файлов (Drag'n'Drop)

10.12.2008 | Категория: Образ мышления: Assembler | Автор: ManHunter
Если в вашем приложении используется обработка файлов, то кроме открытия через стандартные диалоги выбора файла и каталога, можно получать их из Проводника Windows перетаскиванием. Обработка перетаскивания файлов выполняется в два этапа. При инициализации диалогового окна приложения должна вызываться функция DragAcceptFiles. Параметр функции TRUE разрешает принятие файлов окном, а FALSE его запрещает, так что прием файлов можно регулировать динамически. Непосредственно прием файлов окном выполняется функцией DragQueryFile.
  1. ; Сегмент кода
  2. section '.code' code readable executable
  3.         ... 
  4. ; Процедура обработчика окна
  5. proc DialogProc hwnddlg,msg,wparam,lparam 
  6.         ...
  7.         ; Инициализация окна
  8.         cmp     [msg],WM_INITDIALOG
  9.         je      wminitdialog
  10.         ; Обработка перетаскивания файлов
  11.         cmp     [msg],WM_DROPFILES
  12.         je      wmdropfiles
  13.         ...
  14. wminitdialog:
  15.         ; Разрешить окну принимать файлы
  16.         invoke  DragAcceptFiles,[hwnddlg],TRUE
  17.         jmp     processed
  18.  
  19. wmdropfiles:
  20.         ; Обработка полученных файлов. Функция DragQueryFile возвращает имя
  21.         ; файла с указанным индексом (нумерация индексов начинается с нуля).
  22.         ; Для получения общего количества переданных файлов ее надо вызвать с
  23.         ; индексом равным 0FFFFFFFFh
  24.         invoke  DragQueryFile,[wparam],0FFFFFFFFh,NULL,NULL
  25.         ; В регистре EAX количество переданных файлов
  26.  
  27.         ; Перебрать по очереди все переданные окну файлы
  28.         xor     ecx,ecx
  29. process_file:
  30.         push    ecx eax
  31.         ; Получить имя файла или каталога в буфер fname
  32.         invoke  DragQueryFile,[wparam],ecx,fname,100h
  33.         ...
  34.         ; Тут будет обработчик переданных файлов и каталогов
  35.         ...
  36.         pop     eax ecx
  37.         inc     ecx
  38.         cmp     ecx,eax
  39.         jne     process_file
  40.  
  41.         ; Освободить дескриптор операции
  42.         invoke  DragFinish,[wparam]
  43.         ...
Если требуется получить только один файл, то запрашивать общее количество файлов не обязательно, достаточно вызвать DragQueryFile с нулевым индексом файла. Если в интерфейсе предусмотрено несколько полей для приема файлов, то может возникнуть необходимость определять, в какое именно поле выполнятся сброс файла. Делать это можно, например, через субклассирование, но есть способ проще. При помощи функции DragQueryPoint можно определять координаты точки внутри окна, на которых был выполнен бросок файла. Сравнив их с координатами полей ввода, легко определить, какому из них предназначался файл.

После выполнения всех необходимых действий с файлом, надо освободить память, выделенную под файлы, при помощи функции DragFinish.

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

Окно поверх всех окон (Always On Top)

03.12.2008 | Категория: Образ мышления: Assembler | Автор: ManHunter
Установка окна поверх всех других окон бывает удобна, когда надо привлечь внимание пользователя к важной информации, или окно с какими-либо данными должно находиться всегда перед глазами. Такое свойство окна можно прописать сразу в ресурсах, а можно изменять динамически, например при нажатии на кнопку-чекбокс "Always on top" или при изменении каких-нибудь внутренних настроек вашей программы.

Для создания окна поверх всех других окон, оно должно быть описано в ресурсах с флагом DS_SYSMODAL. Для динамического изменения используется функция SetWindowPos с флагами SWP_NOMOVE и SWP_NOSIZE. Флаги нужны для того, чтобы не изменять размеры и положение окна.
  1. ; Идентификатор чекбокса в ресурсах
  2. ID_ONTOP        = 101
  3.  
  4. ; Сегмент кода
  5. section '.code' code readable executable
  6.         ...
  7. ; Процедура обработчика окна
  8. proc DialogProc hwnddlg,msg,wparam,lparam
  9.         ; Обработка нажатия на кнопку-чекбокс
  10.         cmp     [wparam],BN_CLICKED shl 16 + ID_ONTOP
  11.         je      .ontop
  12.         ...
  13. .ontop:
  14.         ; Получить состояние чекбокса
  15.         invoke  IsDlgButtonChecked,[hwnddlg],ID_ONTOP
  16.         cmp     eax,BST_CHECKED
  17.         ; По умолчанию будем считать что галочка поставлена
  18.         mov     eax,HWND_TOPMOST
  19.         je      @f
  20.         ; Галочка не поставлена, убрать атрибут "поверх всех окон"
  21.         mov     eax,HWND_NOTOPMOST
  22. @@:
  23.         ; Установить параметр окна "поверх всех окон", изменение размера
  24.         ; и положения окна не производится, это установлено флагами
  25.         invoke  SetWindowPos,[hwnddlg],eax,0,0,0,0,SWP_NOMOVE+SWP_NOSIZE
  26.         jmp     .processed
  27.         ...
  28.  
  29. ; Секция ресурсов
  30. section '.rsrc' resource data readable
  31. ; Диалог описан со стилем DS_SYSMODAL - поверх всех окон
  32. dialog demonstration, 'Always on top Demo', 0, 0, 190, 55,\
  33.         WS_CAPTION+WS_SYSMENU+DS_CENTER+DS_SYSMODAL
  34.         ...
  35.         ; Кнопка-чекбокс, которая будет управлять положением окна
  36.         dialogitem 'BUTTON','Always on top', ID_ONTOP, 5, 150, 63, 13,\
  37.         WS_VISIBLE+BS_AUTOCHECKBOX+BS_FLAT
  38.         ...
В приведенном примере при поставленной галочке "Always on top" окно будет находиться поверх других окон. Исходник с откомпилированным файлом прилагается.

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

Расчет хеша MD5 на Ассемблере

23.11.2008 | Категория: Образ мышления: Assembler | Автор: ManHunter
Функция расчета хеша MD5 на Ассемблере. Готовых решений на FASM как всегда не было, пришлось портировать из MASM. Для работы процедуры в сегменте .data надо подготовить следующие данные:
  1. ; Сегмент данных
  2. section '.data' data readable writeable  
  3. ...
  4. ; Шаблоны функции wsprintf для перевода хеша в строковый вид,
  5. ; при необходимости можно оставить только какой-нибудь один
  6. szMD5Format1 db '%.8X%.8X%.8X%.8X',0  ; Для получения заглавных букв
  7. szMD5Format2 db '%.8x%.8x%.8x%.8x',0  ; Для маленьких букв в строке хеша
  8.  
  9. stMD5Result:
  10.   stdtA      dd ?   ; Переменные для получения и хранения
  11.   stdtB      dd ?   ; результата хеширования
  12.   stdtC      dd ?
  13.   stdtD      dd ?
  14.  
  15. stMD5Hash    rb 33  ; Буфер для строки хеша в формате ASCIIZ
А вот собственно сама процедура хеширования и пример использования:

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

Создание выпадающего списка (Combobox)

13.11.2008 | Категория: Образ мышления: Assembler | Автор: ManHunter
Выпадающий список ComboBox описывается через ресурсы, но заполняется элементами отдельно, на этапе инициализации родительского окна. Для удобства заполнения выпадающих списков я написал и использую такой код.
  1. ; Идентификатор списка в ресурсах 
  2. ID_LIST        = 104
  3.  
  4. ; Сегмент данных
  5. section '.data' data readable writeable 
  6.  
  7. ; Элементы списка в формате ASCIIZ
  8. items   db 'item 0',0
  9.         db 'item 1',0
  10.         db 'item 2',0
  11.         db 'item 3',0
  12.         db 0           ; Признак окончания списка
  13.  
  14. CtrlID  dd ?           ; Хэндл списка
  15.  
  16. ; Сегмент кода
  17. section '.code' code readable executable
  18.         ...
  19. ; Процедура обработчика окна
  20. proc DialogProc hwnddlg,msg,wparam,lparam 
  21.         ...
  22.         ; Инициализация окна?
  23.         cmp     [msg], WM_INITDIALOG
  24.         je      wminitdialog 
  25.         ...
  26. wminitdialog:
  27.         ...
  28.         ; Заполнение списка строками
  29.         invoke  GetDlgItem,[hwnddlg],ID_LIST
  30.         mov     [CtrlID],eax
  31.         mov     esi,items    ; Указатель на список элементов
  32. fill_list:
  33.         invoke  lstrlen,esi  ; Длина строки
  34.         or      eax,eax
  35.         jz      fill_end
  36.         push    eax
  37.         ; Добавить строку в список
  38.         invoke  SendMessage, [CtrlID], CB_ADDSTRING, 0, esi
  39.         pop     eax
  40.         add     esi,eax      ; Следующий элемент списка
  41.         inc     esi
  42.         jmp     fill_list
  43. fill_end:
  44.         ; Установить пункт ID=2 дефолтным, нумерация ID начинается с 0
  45.         ; По умолчанию дефолтный первый пункт с ID=0
  46.         invoke  SendMessage, [CtrlID], CB_SETCURSEL, 2, FALSE
  47.         ...
  48.  
  49. ; Секция ресурсов
  50. section '.rsrc' resource data readable
  51.         ...
  52.         ; Определение выпадающего списка в ресурсах
  53.         ; 200 - максимальный вертикальный размер раскрываемой области списка,
  54.         ; высота самого элемента расчитывается автоматически и в ресурсах
  55.         ; изменить ее невозможно
  56.         dialogitem 'COMBOBOX', '', ID_LIST, 2, 10, 150, 200,\
  57.         WS_VISIBLE+CBS_DROPDOWNLIST+CBS_HASSTRINGS+WS_VSCROLL
  58.         ...
Более подробное описание флагов и стилей списка читайте на Microsoft Developer Network. Через сообщение CB_ADDSTRING можно в любое время динамически добавлять новые элементы к уже созданному списку, а через CB_SETCURSEL менять текущий выбранный элемент. Это удобно использовать при создании нескольких взаимосвязанных списков. Все добавляемые строки списка должны быть в формате ASCIIZ.

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

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