PureBasic allows you to include any x86 assembler commands (including MMX and FPU one) directly
in the source code, as if it was a real assembler. And it gives you even more: you can use directly
any variables or pointers in the assembler keywords, you can put any ASM commands on the same line, ...
On Windows and Linux, PureBasic uses fasm (http://flatassembler.net), so if you want more information about
the syntax, just read the fasm guide.
On OS X, PureBasic uses yasm (http://yasm.tortall.net/), so if you want more information about
the syntax, just read the yasm guide.

To activate the inline assembler use the compiler directives EnableASM and DisableASM.
It's possible to enable the ASM syntax coloring in the IDE with the "enable inline ASM syntax coloring" compiler option.

Rules

You have several rules to closely follow if you want to include ASM in a BASIC code :

- The used variables or pointers must be declared before to use them in an assembler keyword.
Their names in assembler are 'v_variablename' and 'p_pointername', and in a procedure their names are
'p.v_variablename' and 'p.p_pointername'.
- Labels: The labels need to be referenced in lowercase when using the in-line ASM.
When you reference a label, you must put the prefix 'l_' before the name.
If the label is defined in a procedure, then its prefix is 'll_procedurename_', in lowercase.
When you reference a module item, you must put the prefix 'module_name.l_' all in lowercase before the item.
If the label is defined in a procedure inside a module, then its prefix is 'module_name.ll_procedurename_', in lowercase.

Example

DeclareModule MyModule
LabelDeclareModule: ;Its name is mymodule.l_labeldeclaremodule:DeclareInit()
EndDeclareModuleModule MyModule
ProcedureInit()
LabelModuleProcedure: ; Its name is mymodule.ll_init_labelmoduleprocedure: Debug "InitFerrari()"
EndProcedure
LabelModule1: ;Its name is mymodule.l_labelmodule1:EndModuleProcedureTest (*Pointer, Variable)
TokiSTART: ;Its name is ll_test_tokistart:
! MOV dword [p.p_Pointer], 20
! MOV dword [p.v_Variable], 30
Debug *Pointer ;Its name is p.p_PointerDebug Variable ;Its name is p.v_VariableEndProcedure
VAR=1 ;Its name is v_VAR
*Pointt=AllocateMemory(10) ;Its name is p_Pointt
MyModule::Init()
Test(0,0)
Label1: ;Its name is l_label1:
!jmp l_labelend ; An instruction in assembler has to use the rules above. Here it's l_namelabel;...
LabelEnd: ;Its name is l_labelend:

- The errors in an ASM part are not reported by PureBasic but by FASM. Just check your code if a such error happen.
- With enabled InlineASM you can't use ASM keywords as label names in your source.
- On x86 processors, the available volatile registers are: eax, ecx and edx, xmm0, xmm1, xmm2 and xmm3. All others must be always preserved.
- On x64 processors, the available volatile registers are: rax, rcx, rdx, r8, r9, xmm0, xmm1, xmm2 and xmm3. All others must be always preserved.
- Windows only: an ASM help-file could be downloaded here. If you place the 'ASM.HLP' in the 'Help/' folder of PureBasic,
you can also get help on ASM keywords with F1. (Note: this feature is only enabled, when InlineASM is enabled).

When using assembler in a procedure, you have to be aware of several important things:

- To return directly the 'eax' (or 'rax' on x64) register content, just use ProcedureReturn, without any expression.
It will let the 'eax' (or 'rax' on x64) register content untouched and use it as return-value.

Example

Procedure.l MyTest()
MOV eax, 45
ProcedureReturn; The returned value will be 45EndProcedure

- Local variables in PureBasic are directly indexed by the stack pointer, which means if
the stack pointer change via an ASM instruction (like PUSH, POP etc..) the variable index will
be wrong and direct variable reference won't work anymore.

- It's possible to pass directly an assembly line to the assembler without being processed by the compiler
by using the '!' character at the line start. This allow to have a full access to the assembler directives.
When using this, it's possible to reference the local variables using the notation
'p.v_variablename' for a regular variable or 'p.p_variablename' for a pointer.