Встроенный x86 ASM
Введение
PureBasic позволяет вам вставить любые команды ассемблера x86 (включая MMX и FPU) прямо в исходный код, как если бы это был настоящий ассемблер. Она даёт вам даже более того: вы можете прямо использовать любые переменные или указатели в ключевых словах ассемблера, вы можете помещать любые команды ассемблера в одной строке. На Windows и Linux, PureBasic использует Fasm (http://flatassembler.net), так что если Вы хотите больше информации о синтаксисе ассемблера, просто прочитайте руководство по Fasm.
На OS X PureBasic использует yasm (http://yasm.tortall.net/), поэтому если вы хотите больше информации о синтаксисе ассемблера, просто прочитайте руководство по yasm.
Чтобы активировать встроенный ассемблер используйте директивы компилятора EnableASM и DisableASM.
Можно включить подсветку синтаксиса ASM в IDE, с помощью параметра "Подсветка синтаксиса ASM инструкций" в Настройках компилятора .
Правила
Вам придётся строго следовать нескольким правилам, если вы хотите включать ASM в код PureBasic:
- Используемые Переменные и Указатели должны быть объявлены перед использованием их в ключевом слове ассемблера. Их имена в ассемблере - это 'v_variablename' и 'p_pointername', а в процедуре их имена 'p.v_variablename' и 'p.p_pointername'.
- Метки: При использовании встроенного ASM на метки нужно ссылаться в нижнем регистре. Когда вы ссылаетесь на метку, перед её именем вы должны поставить префикс 'l_'. Если метка определена в процедуре, то ее префиксом будет 'll_procedurename_' в нижнем регистре. Когда вы ссылаетесь на элемент модуля, перед элементом вы должны поставить префикс 'module_name.l_' в нижнем регистре. Если метка определена в процедуре внутри модуля, то ее префиксом является 'module_name.ll_procedurename_' в нижнем регистре.Пример
DeclareModule MyModule LabelDeclareModule: ; Её имя: mymodule.l_labeldeclaremodule: Declare Init() EndDeclareModule Module MyModule Procedure Init() LabelModuleProcedure: ; Её имя: mymodule.ll_init_labelmoduleprocedure: Debug "InitFerrari()" EndProcedure LabelModule1: ; Её имя: mymodule.l_labelmodule1: EndModule Procedure Test(*Pointer, Variable) TokiSTART: ; Его имя: ll_test_tokistart: ! MOV dword [p.p_Pointer], 20 ! MOV dword [p.v_Variable], 30 Debug *Pointer ; Его имя: p.p_Pointer Debug Variable ; Его имя: p.v_Variable EndProcedure VAR=1 ; Её имя: v_VAR *Pointt=AllocateMemory(10) ; Его имя: p_Pointt MyModule::Init() Test(0, 0) Label1: ; Её имя: l_label1: !jmp l_labelend ; Инструкция на ассемблере должна использовать приведенные выше правила. Здесь это l_namelabel ;... LabelEnd: ; Её имя: l_labelend:
- Ошибки в ассемблерной части кода сообщаются не компилятором PureBasic, а компилятором FAsm. Просто проверьте ваш код, если такие ошибки имеют место.
- При включенном встроенном ассемблере вы не сможете использовать ключевые слова ассемблера в качестве имён меток в вашем исходном коде.
- На x86 процессорах доступные энергозависимые регистры: eax, ecx, edx, xmm0, xmm1, xmm2 и xmm3. Все другие должны всегда сохраняться.
- На x64 процессорах доступные энергозависимые регистры: rax, rcx, rdx, r8, r9, xmm0, xmm1, xmm2 и xmm3. Все другие должны всегда сохраняться.
- Только для Windows : справочный файл ASM можно загрузить здесь. Если Вы поместите 'ASM.HLP' в папку 'Help/' PureBasic, Вы можете также получить справку на ключевых словах ASM с F1. Примечание: эта опция работает , только когда Встроенный x86 ASM активирован.
При использовании ассемблера в процедуре Вы должны знать о нескольких важных вещах:
- Чтобы возвратить непосредственно содержимое регистра 'eax' (или 'rax' на x64), просто используйте команду ProcedureReturn без какого-либо выражения. Она позволит содержимому регистра eax (или 'rax' на x64) остаться нетронутым и использует его как возвращаемое значение.Пример
Procedure.l MyTest() MOV eax, 45 ProcedureReturn ; Возвращенное значение будет 45 EndProcedure
- Локальные переменные в PureBasic индексируются прямо по указателю стека, это означает, что если указатель стека изменяется посредством инструкции ассемблера (такой как PUSH, POP и т.д..), индексация переменных будет нарушена и прямые ссылки на переменные больше работать не будут.
- Можно передать ассемблерную строку прямо ассемблеру без обработки её компилятором с помощью символа '!' в начале строки. Это позволяет иметь полный доступ к директивам ассемблера. При использовании этого приёма можно ссылаться на локальные переменные с помощью нотации 'p.v_variablename' для обычной переменной или 'p.p_variablename' для указателя.Пример
Procedure Test(*Pointer, Variable) ! MOV dword [p.p_Pointer], 20 ! MOV dword [p.v_Variable], 30 Debug *Pointer Debug Variable EndProcedure Test(0, 0)
Пример
AsmInline.pb