Inline assembler

Автор обещает много интересных штучек.

Модератор: The trick

The trick
Постоялец
Постоялец
 
Сообщения: 781
Зарегистрирован: 26.06.2010 (Сб) 23:08

Inline assembler

Сообщение The trick » 11.01.2016 (Пн) 16:06

Всем привет.
Бывают ситуации когда в VB нужно использовать ассемблер. Обычно для этого используют предварительно скомпилированный код размещенный в памяти и запускают его одним из миллиона способов. Очевидным недостатком этого метода является то, что любая модификация ассемблерного кода требует изменения в процедурах размещения кода в памяти. К тому же это является довольно медленной процедурой. Я написал Add-in, который делает вышеописанные процедуры автоматически, а также после компиляции никакие дополнительные действия по размещению кода не выполняются - ассемблерный код влинковывается в EXE. Ассемблерный код работает и в IDE и в скомпилированном (только Native!) коде.

Как этим пользоваться?
Для начала нужно установить Add-in (установщик доступен по ссылке ниже). После установки нужно запустить его из VB (Add-Ins -> Add-in Manager -> Inline assembler). После этого в меню добавится одноименный пункт. Если проект еще не использовал функционал Add-in'а то при первой активации добавится стандартный модуль, в который нужно будет добавить прототипы ассемблерных функций для VB6. Сам модуль можно переименовывать, добавлять процедуры/функции, но размещать в них какой-либо функционал запрещено. После создания модуля можно уже открыть сам редактор ассемблерного кода. В нем доступен раскрывающийся список с именами функций, определенных в добавленном модуле. Для каждой функции можно переопределить код используя синтаксис ассемблера NASM, однако если кода нет, то функция не модифицируется (т.е. получается обычный вызов пустой функции). С каждым проектом (если использовался функционал Add-in'а) связывается еще один файл с расширением *ia в папке с файлом проекта, в котором хранятся ассемблерные процедуры для проекта. Add-in работает "прозрачно", т.е. если Add-in отключен, то проект также будет работать и компилироваться, просто "функции-пустышки" будут работать как обычные. Файл *ia не является жизненно-необходимым для работы проекта, если его не будет, то соответственно "функции-пустышки" останутся нетронутыми.
Давайте посмотрим работу Add-in'а на простом примере. К примеру нам необходимо сложить два Integer-массива без переполнения, т.е. если результат сложения больше 32767 он и останется 32767, а если меньше -32768 он останется -32768. К тому же нам нужно сделать это как можно быстрее. Для этого очень хорошо подходит расширение MMX, в нем есть инструкции для работы с векторными данными с насыщением. Перейдем к реализации. Создадим новый проект, откроем Add-in. Это добавит новый модуль, переименуем его в modInlineAsm. Теперь определим прототип функции:
Код: Выделить всё
Public Function MMXAdd( _
                ByRef dest As Integer, _
                ByRef src As Integer, _
                ByVal count As Long) As Long
End Function

Первым параметром передаем первый элемент массива, он же результирующий; вторым параметром первый элемент второго массива; наконец третьим параметром передаем количество элементов. Кстати размер массивов должен быть кратен 8 байтам, т.к. мы будем использовать векторные инструкции которые одновременно работают с 8-ю байтами. Теперь определим процедуру в форме, которая будет вызывать эту функцию:
Код: Выделить всё
Private Sub Form_Load()
    Dim src()   As Integer
    Dim dst()   As Integer
    Dim size    As Long
    Dim index   As Long
   
    size = 1024
   
    ReDim src(size - 1)
    ReDim dst(size - 1)
   
    For index = 0 To size - 1
        ' // Fill arrays with sine
        src(index) = Sin(index / 40) * 20000
        dst(index) = Sin(index / 23) * 20000
    Next
   
    ' // Add with saturation
    MMXAdd dst(0), src(0), size
   
    '// Draw result
    AutoRedraw = True
   
    Scale (0, 32767)-(index, -32768)
   
    For index = 0 To size - 1
        If index Then
            Me.Line -(index, dst(index))
        Else
            Me.PSet (index, dst(index))
        End If
    Next
   
End Sub

Как видно здесь просто заполняются 2 массива синусоидой, а потом мы их складываем с помощью нашей функции, и выводим результат на форму в виде графика. Теперь нам нужно переопределить процедуру, для этого активируем Add-in. Откроется окно с редактором кода. В нем мы выбираем нашу функцию и добавляем следующий ассемблерный код:
Код: Выделить всё
BITS 32

; Addition of two arrays using saturation
; Size of arrays should be a multiple of 8

push    EBP
mov   EBP, ESP
push    EBX
push    ESI
push    EDI
mov   ESI,DWORD [EBP+0x8]
mov   EDI,DWORD [EBP+0x0C]
mov   ECX,DWORD [EBP+0x10]
shr   ECX,2

test   ECX,ECX
je   EXIT_PROC
emms   ; Initialize MMX

CYCLE:
   movq   MM0,QWORD [EDI]
   movq   MM1,QWORD [ESI]
   paddsw   MM1,MM0
   movq   QWORD [ESI],MM1
   add   ESI,0x8
   add   EDI,0x8
loop   CYCLE

emms

EXIT_PROC:
pop    EDI
pop   ESI
pop   EBX
mov   esp, ebp
pop   ebp

ret   0x0c

Здесь все просто, если знать инструкции. Самая главная paddsw складывает два четырехмерных вектора 16-битных значений со знаком за одну операцию. Теперь сохраняем проект и запускаем:
MMX_test.PNG
MMX_test.PNG (20.72 Кб) Просмотров: 5658

Как видно из скриншота, две синусоиды сложились причем с насыщением, это можно заметить по пикам. Теперь давайте попробуем скомпилировать EXE файл и посмотреть что у нас вызывается и во что компилируется:
Disasm_Listing.PNG
Disasm_Listing.PNG (29.55 Кб) Просмотров: 5658

Как видим код уже находится внутри EXE, без всяких выделений буферов и т.п. ненужных вещей.

Как это работает?
На самом деле все довольно просто. В самом начале ставятся обработчики на ключевые события вроде компиляции, запуска кода, закрытия/сохранения проекта и т.п. При запуске из IDE компилируются все коды заданные пользователем, а также вычисляются адреса переопределяемых функций. Затем код переписывается на код скомпилированный через NASM. И при вызове кода, вызывается наш код. При остановке, код восстанавливается. При компиляции (а точнее перед линковкой) ищется OBJ файл переопределяемого модуля и код функций пустышек переписывается на ассемблерный код, и файл пересохраняется. Для этого я специально писал COFF парсер. Вообще это открывает кучу разных возможностей от замены функций рантайма на свои до шифрования кода. Вообщем много чего можно придумать.

Проект, можно сказать, совсем не тестировался, т.к. у меня в ближайшее время не будет такой возможности, поэтому скорее-всего будет много багов, учитывая то, что половина функционала Add-in'а использует недокументированные трюки, которые возможно работают не так как я думаю. В проекте нет даже подсветки синтаксиса, у меня есть мой самодельный текстбокс с подсветкой написанный с нуля, но его нужно дебажить еще и дописывать, поэтому пока я использовать стандартный текстбокс. Если кого-нибудь заинтересует, и будут баги, пишите сюда.
Кстати, я редко стал писать сюда, да и вообще бывать на форуме, но это не значит что я перестал заниматься VB, у меня еще много проектов которые наполовину реализованы. К примеру готовится проект для использования оптимизаций компиляции в IDE, т.е. отключить переполнения при арифметических операциях для использования циклической арифметики в IDE, а также проверку границ массивов в IDE.
Также к примеру вот:

-нативная загрузка PNG а альфаканалом в IDE в любые контролы. Так что ждите).
Всем спасибо за внимание.
Вложения
setup.zip
Add-in
(880.52 Кб) Скачиваний: 241
UA6527P

ger_kar
Продвинутый гуру
Продвинутый гуру
Аватара пользователя
 
Сообщения: 1957
Зарегистрирован: 19.05.2011 (Чт) 19:23
Откуда: Кыргызстан, Иссык-Куль, г. Каракол

Re: Inline assembler

Сообщение ger_kar » 12.01.2016 (Вт) 21:58

Интересная разработка. Завтра все опробую своими руками :)
И поддержка png, тоже актуальна ибо ее отсутствие в VB6 очень сильно раздражает.
Бороться и искать, найти и перепрятать

The trick
Постоялец
Постоялец
 
Сообщения: 781
Зарегистрирован: 26.06.2010 (Сб) 23:08

Re: Inline assembler

Сообщение The trick » 13.01.2016 (Ср) 22:51

А вот что можно делать к примеру используя возможности этого Add-in'а:

Это VST плагин - эффект Bitcrusher, который полностью написан на VB6.
UA6527P

ger_kar
Продвинутый гуру
Продвинутый гуру
Аватара пользователя
 
Сообщения: 1957
Зарегистрирован: 19.05.2011 (Чт) 19:23
Откуда: Кыргызстан, Иссык-Куль, г. Каракол

Re: Inline assembler

Сообщение ger_kar » 13.01.2016 (Ср) 23:09

А почему именно NASM был выбран? Почему не FASM например, он тоже свободно распространяемый.
Add-in по сути целиком подменяет тело функций пустышек и если развивать это направление дальше, то наверное с таким же успехом можно наверное эти функции писать не только на ассемблере, а на том же Си например. В каких то случаях это может быть даже привлекательнее, ибо в функциях написанных с использование Си, можно комбинировать Сишный код с ассемблерными вставками. Так как писать сложные функции целиком на ассемблере достаточно трудоемкая задача.
Бороться и искать, найти и перепрятать

The trick
Постоялец
Постоялец
 
Сообщения: 781
Зарегистрирован: 26.06.2010 (Сб) 23:08

Re: Inline assembler

Сообщение The trick » 13.01.2016 (Ср) 23:13

ger_kar писал(а):А почему именно NASM был выбран? Почему не FASM например, он тоже свободно распространяемый.

Потому что я всегда писал только на MASM'e и NASM'е и знаю что NASM поддерживает компиляцию в бинарник. FASM тоже поддерживает компиляцию, можно и его использовать, только заменив параметры командной строки. Кстати в FASM'е можно к примеру комбинировать 64-битный и 32-битный код? По хорошему нужно свой ассемблер писать, тогда можно будет без проблем из ассемблера обращаться к переменным и функциям VB6 проекта.
UA6527P

ger_kar
Продвинутый гуру
Продвинутый гуру
Аватара пользователя
 
Сообщения: 1957
Зарегистрирован: 19.05.2011 (Чт) 19:23
Откуда: Кыргызстан, Иссык-Куль, г. Каракол

Re: Inline assembler

Сообщение ger_kar » 13.01.2016 (Ср) 23:27

А я как раз про NASM ничего не знаю, только после прочтения этой статьи прочел в википедии, что это такое :)
The trick писал(а):Кстати в FASM'е можно к примеру комбинировать 64-битный и 32-битный код?
Что то даже и не в курсе. Мне вообще не приходилось 64-битный код писать.
Бороться и искать, найти и перепрятать

Хакер
Телепат
Телепат
Аватара пользователя
 
Сообщения: 16478
Зарегистрирован: 13.11.2005 (Вс) 2:43
Откуда: Казахстан, Петропавловск

Re: Inline assembler

Сообщение Хакер » 14.01.2016 (Чт) 0:24

ger_kar писал(а):В каких то случаях это может быть даже привлекательнее, ибо в функциях написанных с использование Си, можно комбинировать Сишный код с ассемблерными вставками.

Чего только люди не придумают, лишь бы по нормальному DLL не делать. Да и просто можно сишную функцию по обычному скомпилировать и obj прилинковать. Не обязательно для этого придумывать специальный Add-in.

И вообще, моя позиция по новыми фишками и Add-in'ам состоит в том, что фишки должны решаться на уровне кода, а не на уровне расширения/модификации среды, так, чтобы во-первых код можно было бы собрать под свежеустановленной специально не модифицированной средой (чтобы он вообще под ней стал компилироваться), и во-вторых, как следствие, чтобы наличие/отсутствие Add-in'а не меняло бы логики работы работы скомпилированного продукта.

Поэтому отличное применение для Add-in'ов — это опциоальные расширения и улучшения среды. Добавление скролла колесом, добавление поддержки сворачивания блоков кода, быстрое отключение TLB на время перекомпиляции и тому подобные вещи, которые упрощают пользование средой, делает его более удобным, но не становится обязательным критически необходимым фактором для самой возможности скомпилировать проект.

Поэтому даже FNDLL первый был сделан так, что даже без установленного FNDLL заточенный под него проект отлично компилировался (хоть экспорты и не появлялись). Полученный бинарник мог в последствие быть модифицирован модификатором когда угодно в отрыве от самой среды, то есть утилита-модификатор может расцениваться как часть тулчейна, а не как кастом-мод уже существующего инструмента разработки.

Это я к тому говорю, что подход с обычной DLL или подход с прилинковыванием при помощи найденных мною ключей соответствуют такой идеологии.
—We separate their smiling faces from the rest of their body, Captain.
—That's right! We decapitate them.

Qwertiy
Доктор VB наук
Доктор VB наук
 
Сообщения: 2753
Зарегистрирован: 26.06.2011 (Вс) 21:26

Сообщение Qwertiy » 14.01.2016 (Чт) 19:23

Хакер писал(а):И вообще, моя позиция по новыми фишками и Add-in'ам состоит в том, что фишки должны решаться на уровне кода, а не на уровне расширения/модификации среды, так, чтобы во-первых код можно было бы собрать под свежеустановленной специально не модифицированной средой (чтобы он вообще под ней стал компилироваться), и во-вторых, как следствие, чтобы наличие/отсутствие Add-in'а не меняло бы логики работы работы скомпилированного продукта.

Но ведь если будет нельзя собрать, то в этом ничего плохого нет - надо будет просто поставить add-in.
А вот если можно собрать, но он работает не так, как ожидается, то это уже плохо.

Хакер
Телепат
Телепат
Аватара пользователя
 
Сообщения: 16478
Зарегистрирован: 13.11.2005 (Вс) 2:43
Откуда: Казахстан, Петропавловск

Re: Inline assembler

Сообщение Хакер » 14.01.2016 (Чт) 19:35

Qwertiy писал(а):Но ведь если будет нельзя собрать, то в этом ничего плохого нет - надо будет просто поставить add-in.

Плохое в этом есть.
Человек, которому придётся компилировать проект, может банально не знать, что вообще за Add-in необходим. А если знать, что за Add-in, то не знать, где его взять. Или даже если он будет знать где, сам по себе Add-in может быть недоступен, потому что сайт разработчика рухнул.

Кирпичи в этом плане хороши — они распространяются вместе с проектом как его часть. Не будешь же add-in класть в каталог в спроектом и подвергать его версионному контролю, например?
—We separate their smiling faces from the rest of their body, Captain.
—That's right! We decapitate them.

Qwertiy
Доктор VB наук
Доктор VB наук
 
Сообщения: 2753
Зарегистрирован: 26.06.2011 (Вс) 21:26

Сообщение Qwertiy » 14.01.2016 (Чт) 23:16

Хакер писал(а):Не будешь же add-in класть в каталог в спроектом и подвергать его версионному контролю, например?

А что мешает исходники add-in'а на том же гитхабе разместить?

Хакер
Телепат
Телепат
Аватара пользователя
 
Сообщения: 16478
Зарегистрирован: 13.11.2005 (Вс) 2:43
Откуда: Казахстан, Петропавловск

Re: Inline assembler

Сообщение Хакер » 14.01.2016 (Чт) 23:19

Qwertiy писал(а):А что мешает исходники add-in'а на том же гитхабе разместить?

1. Это вопрос не ко мне.
2. Почему упоминание версионного контроля автоматически подразумевает использование публичного хостинга для git-репозиториев?
3. Не очень хорошо, что для работы с проектом кому-то понадобится клонировать репозиторий, компилировать и затем инсталлировать дополнение к среде разработки.
—We separate their smiling faces from the rest of their body, Captain.
—That's right! We decapitate them.

Debugger
Продвинутый гуру
Продвинутый гуру
Аватара пользователя
 
Сообщения: 1667
Зарегистрирован: 17.06.2006 (Сб) 15:11

Re: Inline assembler

Сообщение Debugger » 15.01.2016 (Пт) 13:52

Прикольная и простая штука, но, жаль, NASM мне незнаком. Продолжу писать библиотеки на Сях.

Я верно понимаю, что содержимое вставки общается с VB6-проектом только посредством передаваемых переменных и возвращаемого значения?

Хакер писал(а):
Qwertiy писал(а):А что мешает исходники add-in'а на том же гитхабе разместить?

3. Не очень хорошо, что для работы с проектом кому-то понадобится клонировать репозиторий, компилировать и затем инсталлировать дополнение к среде разработки.

Это распространено, повсеместно.

The trick
Постоялец
Постоялец
 
Сообщения: 781
Зарегистрирован: 26.06.2010 (Сб) 23:08

Re: Inline assembler

Сообщение The trick » 15.01.2016 (Пт) 18:06

Debugger писал(а):Я верно понимаю, что содержимое вставки общается с VB6-проектом только посредством передаваемых переменных и возвращаемого значения?

Пока да, но думаю не проблема будет сделать обращение к переменным и функциям. В IDE это не имеет проблемы, я могу сделать это и сейчас. Для скомпилированного варианта нужно немного подумать как правильнее сделать. Пока времени нет этим заниматься.
UA6527P

Qwertiy
Доктор VB наук
Доктор VB наук
 
Сообщения: 2753
Зарегистрирован: 26.06.2011 (Вс) 21:26

Сообщение Qwertiy » 16.01.2016 (Сб) 11:45

Хакер писал(а):2. Почему упоминание версионного контроля автоматически подразумевает использование публичного хостинга для git-репозиториев?

Скорее, упоминание того, что сайт автора может исчезнуть приводит к мысли, что надо расположить там, где не исчезнет.

Хакер писал(а):3. Не очень хорошо, что для работы с проектом кому-то понадобится клонировать репозиторий, компилировать и затем инсталлировать дополнение к среде разработки.

Хм.. Вроде в репозиториях обычно есть возможность скачать бинарники. Собирать каждый раз add-in из исходников было бы странно, да.

Хакер
Телепат
Телепат
Аватара пользователя
 
Сообщения: 16478
Зарегистрирован: 13.11.2005 (Вс) 2:43
Откуда: Казахстан, Петропавловск

Re: Inline assembler

Сообщение Хакер » 16.01.2016 (Сб) 19:40

Qwertiy писал(а):надо расположить там, где не исчезнет.

Такого вообще не бывает.

Qwertiy писал(а):Хм.. Вроде в репозиториях обычно есть возможность скачать бинарники. Собирать каждый раз add-in из исходников было бы странно, да.

Речь абсолютно не о технических ограничениях репозиториев. Речь об идеологии.
—We separate their smiling faces from the rest of their body, Captain.
—That's right! We decapitate them.


Вернуться в The trick

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 3

    TopList