Asm

Code block that allows the use of architecture-specific instructions.

Syntax
   Asm
      architecture-dependent instructions
   End Asm

      Or

   Asm architecture-dependent instructions

Description
   The Asm block is used to insert specific machine-code instructions in a 
   program in order to perform operations that cannot be carried out using 
   the features of the language or to hand-optimize performance-sensitive 
   sections of code.

   The current FreeBASIC compiler currently only produces code for Intel 
   80x86-based machines; however, in the future, the compiler might be 
   ported to a platform which does not support the same instruction set.  
   Therefore, Asm blocks should only be used when necessary, and a 
   FreeBASIC-only alternative should be provided if possible.

   The return value of a function may be set by using the Function keyword 
   within brackets as shown in the example below.

   Asm block comments have the same syntax as usual FreeBASIC Comments  - 
   use FreeBASIC-like " ' " comments, not " ; " as usual in assembly code. 

   x86 Specific:

      Syntax
         The syntax of the inline assembler is a simplified form of Intel 
         syntax.  Intel syntax is used by the majority of x86 assemblers, 
         such as MASM, TASM, NASM, YASM and FASM. In general, the 
         destination of an instruction is placed first, followed by the 
         source. Variables and functions defined by a program may be 
         referenced in an Asm block.  The assembler used by FreeBASIC is 
         GAS, using the .intel_syntax noprefix directive, and Asm blocks 
         are passed through unmodified, except for the substitution of 
         local variable names for stack frame references, and commenting 
         removal.

         Instruction syntax is mostly the same as FASM uses, one important 
         difference is that GAS requires size settings to be followed by 
         the word "ptr".

   ' Assuming "n" is a FB global or local ULONG variable
   mov  eax, [n]        ' OK: size is apparent from eax
   inc  [n]             ' Not OK: size is not given
   inc  dword [n]       ' Not OK: size given, but still not accepted by GAS
   inc  dword Ptr [n]   ' OK: "ptr" is needed by GAS here

      Register Preservation
         When an Asm block is opened, the registers ebx, esi, and edi are 
         pushed to the stack, when the block is closed, these registers are 
         popped back from the stack.  This is because these registers are 
         required to be preserved by most or all OS's using the x86 CPU.  
         You can therefore use these registers without explicitly 
         preserving them yourself. You should not change esp and ebp, since 
         they are usually used to address local variables. 
         Note: Inside a Naked procedure, there is no such register 
         preservation.

      Register Names
         The names of the registers for the x86 architecture are written as 
         follows in an Asm block:
         * 4-byte integer registers: eax, ebx, ecx, edx, ebp, esp, edi, 
           esi
         * 2-byte integer registers: ax, bx, cx, dx, bp, sp, di, si (low 
           words of 4-byte e- registers)
         * 1-byte integer registers: al, ah, bl, bh, cl, ch, dl, dh (low 
           and high bytes of 2-byte -x registers)
         * Floating-point registers: st(0), st(1), st(2), st(3), st(4), 
           st(5), st(6), st(7)
         * MMX registers (aliased onto floating-point registers): mm0, mm1
           , mm2, mm3, mm4, mm5, mm6, mm7
         * SSE registers: xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7

      Instruction Set
         See these external references:
         * Original Intel 80386 manual from 1986
         * Latest Intel Pentium 4 manuals
         * NASM x86 Instruction Reference (Please note that NASM is not 
           the assembler used by FreeBASIC, but this page provides a good 
           overview of x86 instructions)

      Unsafe instructions
         Note that the FreeBASIC compiler produces 32-bit protected-mode 
         code for the x86 which usually runs in an unprivileged user level; 
         therefore, privileged and sensitive instructions will assemble 
         fine, but possibly won't work correctly or cause a runtime 
         "General Protection Fault", "Illegal instruction", or SIGILL 
         error. The following are the privileged and sensitive instructions 
         as of the Intel Pentium 4 and Xeon:
         * cli *1
         * clts
         * hlt
         * in *1
         * ins *1
         * int *1               
         * into *1               
         * invd
         * invlpg
         * lgdt
         * lidt
         * lldt
         * lmsw
         * ltr
         * mov to/from CRn, DRn, TRn
         * out *1
         * outs *1
         * rdmsr
         * rdpmc *2
         * rdtsc *2
         * sti *1
         * str
         * wbinvd
         * wrmsr
         * all SSE2 and higher instructions *2

          *1: sensitive to IOPL, fine in DOS 
          *2: sensitive to permission bits in CR4, see below

   The privileged instructions will work "correctly" in DOS when running on 
   a Ring 0 DPMI kernel, like the (non-default) Ring 0 version of CWSDPMI, 
   WDOSX or D3X, nevertheless most of them are not really useful and 
   dangerous when executed from DPMI code. RDTSC (Read Time Stamp Counter) 
   has been shown to be allowed by most, or all OS'es.

   However the usefulness of RDTSC has been diminished with the advent of 
   multi-core and hibernating CPUs. SSE2 and higher instructions are 
   disabled "by default" after CPU initialization, Windows and Linux 
   usually do enable them, in DOS it is business of the DPMI host: HDPMI32 
   will enable them, CWSDPMI won't. The INT instruction is usable in the 
   DOS version/target only, note that it works slightly differently from 
   real mode DOS, see also FaqDOS.

   The segment registers (cs, ds, es, fs, gs) should not be changed from an 
   Asm block, except in certain cases with the DOS port (note that they do 
   NOT work the same way as in real-mode DOS, see also FaqDOS). The 
   operating system or DPMI host is responsible for memory management; the 
   meaning of segments (selectors) in protected mode is very different from 
   real-mode memory addressing.

   Note that those "unsafe" instructions are not guaranteed to raise a 
   "visible" crash even when ran with insufficient privilege - the OS or 
   DPMI host can decide to "emulate" them, either functionally (reading 
   from some CRx works under HDPMI32), or "dummy" (nothing happens, 
   instruction will pass silently, like a NOP).

Example
   '' This is an example for the x86 architecture.
   Function AddFive(ByVal num As Long) As Long
      Asm
         mov eax, [num]
         Add eax, 5
         mov [Function], eax
      End Asm
   End Function

   Dim i As Long = 4

   Print "4 + 5 ="; AddFive(i)

   4 + 5 = 9

   FreeBASIC's Assembler is AS / GAS, the assembler of GCC, so an external 
   program. Some quirks apply:
      * The error lines  returned by FBC for Asm blocks are not related 
        the FB source file. As FBC simply displays the errors returned by 
        AS , the lines are related to the assembly file. To make FreeBASIC 
        preserve them, the compiler must be invoked with the -R option 
        ("don't delete ASM files").
      * The label names are case sensitive inside Asm blocks.

Dialect Differences
   * Not available in the -lang qb dialect unless referenced with the 
     alias __Asm.

Differences from QB
   * New to FreeBASIC

See also
   * Function
   * Naked

