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

"FASM и UPX: созданы друг для друга"
25.03.2011 | Категория: Образ мышления: Assembler | Автор: ManHunter
Сразу скажу, утро и кофе к этой статье отношения не имеют, все необычные решения приходят ко мне обычно по ночам. Однажды я экспериментировал с FASM, и обнаружил один интересный момент. Ниже приведен ассемблерный листинг самой простейшей программы, она выводит на экран сообщение и сразу же завершает работу, вроде бы ничего необычного.Code (Assembler) : Убрать нумерацию
- section '.code' code readable executable
- start:
- ; Вывести окно сообщения и выйти из программы
- invoke MessageBox, NULL, szMess, szTitle, MB_OK
- invoke ExitProcess,0
- ; Куча пустого места, чтобы можно было упаковать файл
- rd 1000h
- szTitle db 'Title',0
- szMess db 'Hello, UPX ;)',0
- ;---------------------------------------------
- section '.idata' import data readable writeable
- ; Обратите внмание, user32.dll прописан дважды
- library kernel32,'kernel32.dll',\
- user32,'user32.dll',\
- user32,'user32.dll'
- include 'apia\kernel32.inc'
- include 'apia\user32.inc'
Читать статью целиком »
Просмотров: 6251 | Комментариев: 10

Управление лотком CD-ROM на Ассемблере
06.02.2011 | Категория: Образ мышления: Assembler | Автор: ManHunter
Открывать и закрывать лоток CD-ROM можно программными способами. Это может оказаться полезным в случаях, когда системный блок стоит в труднодоступном месте или по каким-либо иным причинам нет возможности управлять им при помощи механической кнопки. Также я читал истории, когда на лоток CD-ROM возлагались полезные функции, например, при выдвижении он замыкал контакты питания и отправлял сервер в перезагрузку, а администратор таким образом удаленно управлял им. Так что программное управление лотком CD-ROM имеет место быть, и наша задача научиться его делать. Чаще всего в разных интернетах описывается способ управления при помощи MCI (Media Control Interface). Кстати, именно этот способ приводится в качестве одного из примеров программ в пакете FASM.Code (Assembler) : Убрать нумерацию
- ...
- ; Открыть лоток CD-ROM
- invoke mciSendString,cmd_open,0,0,0
- invoke mciSendString,cmd_eject,0,0,0
- invoke mciSendString,cmd_close,0,0,0
- ...
- ; Закрыть лоток CD-ROM
- invoke mciSendString,cmd_open,0,0,0
- invoke mciSendString,cmd_load,0,0,0
- invoke mciSendString,cmd_close,0,0,0
- ...
- cmd_open db 'open cdaudio',0
- cmd_eject db 'set cdaudio door open',0
- cmd_load db 'set cdaudio door closed',0
- cmd_close db 'close cdaudio',0
Читать статью целиком »
Просмотров: 10254 | Комментариев: 6

Проверка баланса скобок на Ассемблере
28.01.2011 | Категория: Образ мышления: Assembler | Автор: ManHunter
Есть такая классическая задача по программированию: проверка правильности расстановки скобок в строке, или иначе проверка баланса скобок. Суть задачи заключается в том, что есть произвольное математическое выражение, записанное в строку, в этом выражении используется три вида скобок "( )", "[ ]" и "{ }", последовательность и вложенность может быть любая. Требуется проверить, все ли скобки закрыты, соответствует ли каждая закрывающая скобка открывающей и нет ли лишних закрывающих скобок. В разных интернетах есть решения на различных языках программирования, я решил добавить свое решение на Ассемблере, тем более, что он идеально подходит для реализации этого алгоритма.Решение заключается в том, что мы двигаемся по строке с самого начала, перебирая все символы по одному. Если символ является открывающей скобкой любого типа, то мы помещаем его в стек. Если символ является закрывающей скобкой, то берем из стека последнюю сохраненную открывающую скобку и проверяем на соответствие. Если не совпадают - ошибка несоответствия скобок, если стек пустой, то ошибка лишней закрывающей скобки. Если конец строки достигнут, но стек не пустой, то ошибка незакрытых скобок. Как видите, решение целиком построено на работе со стеком, а Ассемблер предоставляет для этого все возможности. Переходим к программированию.
Code (Assembler) : Убрать нумерацию
- ;------------------------------------------------------------------------
- ; Функция проверки правильности расстановки скобок в выражении
- ; На входе: указатель на строку ASCIIZ
- ; На выходе: EAX - результат проверки выражения
- ; 0 - скобки расставлены правильно
- ; 1 - ОШИБКА: скобки не совпадают
- ; 2 - ОШИБКА: закрывающая скобка без открывающей
- ; 3 - ОШИБКА: открывающая скобка без закрывающей
- ;------------------------------------------------------------------------
- proc CheckBrackets str:DWORD
- local res:DWORD ; Результат
- pusha ; Сохранить все регистры
- mov esi,[str] ; Указатель на строку
- cld
- xor ecx,ecx ; Глубина стека
- mov [res],0 ; Результат проверки
- .scan_expr:
- lodsb ; Прочитать символ из строки
- or al,al ; Конец строки достигнут?
- jz .finish
- ; Проверить открывающие скобки
- cmp al,'['
- je .push_bracket
- cmp al,'('
- je .push_bracket
- cmp al,'{'
- je .push_bracket
- ; Проверить закрывающие скобки
- cmp al,']'
- je .pop_bracket
- cmp al,')'
- je .pop_bracket
- cmp al,'}'
- je .pop_bracket
- jmp .scan_expr ; Следующий символ
- ; Занести скобку в стек
- .push_bracket:
- inc ecx ; Увеличить счетчик
- movzx eax,al ; Записать скобку в стек
- push eax
- jmp .scan_expr ; Следующий символ
- ; Извлечь скобку из стека
- .pop_bracket:
- or ecx,ecx ; В стеке ничего нет?
- jne @f
- ; ОШИБКА: закрывающая скобка без открывающей
- mov [res],2
- jmp .finish
- @@:
- dec ecx ; Уменьшить счетчик
- pop ebx ; Извлечь из стека скобку
- ; Проверить закрывающие скобки
- cmp bl,'['
- jne @f
- cmp al,']' ; Скобки совпадают?
- je .scan_expr ; Да, следующий символ
- @@:
- cmp bl,'('
- jne @f
- cmp al,')' ; Скобки совпадают?
- je .scan_expr ; Да, следующий символ
- @@:
- cmp bl,'{'
- jne @f
- cmp al,'}' ; Скобки совпадают?
- je .scan_expr ; Да, следующий символ
- @@:
- ; ОШИБКА: скобки не совпадают
- mov [res],1
- or ecx,ecx ; В стеке пусто?
- jz .exit ; Да, просто на выход
- jmp .clean_stack ; Надо почистить стек
- .finish:
- or ecx,ecx ; Все проверили и в стеке пусто?
- jz .exit ; Да, скобки расставлены правильно
- ; ОШИБКА: открывающая скобка без закрывающей
- mov [res],3
- ; Почистить стек от оставшихся скобок
- .clean_stack:
- pop eax
- loop .clean_stack
- .exit:
- popa ; Восстановить все регистры
- mov eax,[res]
- ret
- endp
Читать статью целиком »
Просмотров: 7303 | Комментариев: 4

Эффект плавного открытия окна
08.12.2010 | Категория: Образ мышления: Assembler | Автор: ManHunter
Разберем еще один красивый эффект для ваших приложений - плавное сворачивание и разворачивание окна. Для этого используются те же функции, что и для создания окон нестандартной формы, так как по сути это такая же работа с прямоугольными регионами, но только в цикле с заданными параметрами. Алгоритм простой: прямоугольный регион окна увеличивается от центра до полного размера или уменьшается со всех сторон до центра. Для этого надо сперва надо вычислить шаг, на который будет увеличиваться или уменьшаться горизонтальная и вертикальная координата.Code (Assembler) : Убрать нумерацию
- ; Обработчик инициализации окна
- ...
- ; Получить размер окна
- invoke GetClientRect,[hwnddlg],coord
- ; Вычислить размеры окна для создания основного региона
- mov eax,[coord.bottom]
- sub eax,[coord.top]
- mov [height],eax
- mov eax,[coord.right]
- sub eax,[coord.left]
- mov [width],eax
- SPEED = 4 ; Скорость анимации
- ; Вычислить коэффициент соотношения сторон в зависимости от
- ; размеров ширины и высоты окна
- cmp eax,[height]
- ja @f
- ; Высота/ширина
- xor edx,edx
- mov eax,[height]
- mov ecx,[width]
- div ecx
- shl eax,SPEED
- mov [delta_x],(1 shl SPEED) ; Шаг изменения ширины
- mov [delta_y],eax ; Шаг изменения высоты
- jmp @1
- @@:
- ; Ширина/высота
- xor edx,edx
- mov eax,[width]
- mov ecx,[height]
- div ecx
- shl eax,SPEED
- mov [delta_x],eax ; Шаг изменения ширины
- mov [delta_y],(1 shl SPEED) ; Шаг изменения высоты
- @1:
Читать статью целиком »
Просмотров: 6552 | Комментариев: 6

Расчет CRC16 на Ассемблере
30.11.2010 | Категория: Образ мышления: Assembler | Автор: ManHunter
CRC (Cyclic Redundancy Code - циклический избыточный код) - алгоритм расчета контрольной суммы для передаваемого сообщения, основанный на полиномиальной арифметике. Основная идея алгоритма CRC состоит в представлении сообщения в виде огромного двоичного числа, делении его на другое фиксированное двоичное число и использовании остатка от этого деления в качестве контрольной суммы. Получив сообщение, приемник должен выполнить аналогичное действие и сравнить полученный результат с принятой контрольной суммой. Сообщение считается достоверным, выполняется это равенство. Классический алгоритм CRC16 часто используется в архиваторах для контроля целостности данных служебных заголовков архивов, также его удобно использовать для сравнения строки с каким-либо значением, когда по соображениям безопасности сравниваемое значение не хранится в открытом виде. Для контроля целостности файлов функцию CRC16 лучше не использовать, так как из-за небольшой длины ее научились подделывать. Чтобы выполнить расчет CRC16 требуется сперва подготовить так называемую таблицу инициализации. В сегменте данных таблица резервируется как 256 слов, по одному word на каждый возможный байт:Code (Assembler) : Убрать нумерацию
- ; Сегмент данных
- section '.data' data readable writeable
- ; Таблица инициализации для расчета CRC16
- crc16table rw 256
Code (Assembler) : Убрать нумерацию
- ;-----------------------------------------------------------------------
- ; Функция создания таблицы инициализации для расчета CRC16
- ;-----------------------------------------------------------------------
- proc init_CRC16
- push eax ebx ecx edi
- ; Указатель на выделенную под таблицу память
- mov edi,crc16table
- ; Расчитать значения для всех 256 слов
- xor edx,edx
- CRC16_Polynom:
- mov eax,edx
- mov ecx,8
- CRC16_NL:
- shr ax,1
- jae CRC16_NoXOR
- ; Magic Number!
- xor ax,0a001h
- CRC16_NoXOR:
- loop CRC16_NL
- ; Записать значение в таблицу полиномов
- stosw
- inc edx ; Счетчик +1
- cmp edx,256 ; Всю таблицу сгенерировали?
- jne CRC16_Polynom ; Нет, работаем дальше
- ; Восстановить измененные регистры
- pop edi ecx ebx eax
- ret
- endp
Читать статью целиком »
Просмотров: 11358 | Комментариев: 2
