Sign in Join
Wiki copytemporary

Asm

Deutsch · English · Español · Suomi

The reserved word asm starts a frame of inline assembly code.

pascal
program asmDemo(input, output, stderr);

// The $asmMode directive informs the compiler
// which syntax is used in asm-blocks.
// Alternatives are 'att' (AT&T syntax) and 'direct'.
{$asmMode intel}

var
    n, m: longint;
begin
    n := 42;
    m := -7;
    writeLn('n = ', n, '; m = ', m);
    
    // instead of declaring another temporary variable
    // and writing "tmp := n; n := m; m := tmp;":
    asm// eax := n// xchg can only operate at most on one memory address// swaps values in eax and at m// n := eax (holding the former m value)// an array of strings after the asm-block closing 'end'// tells the compiler which registers have changed// (you don't wanna mess with the compiler's notion// which registers mean what)
        mov eax, n  // eax := n
        // xchg can only operate at most on one memory address
        xchg eax, m // swaps values in eax and at m
        mov n, eax  // n := eax (holding the former m value)
    // an array of strings after the asm-block closing 'end'
    // tells the compiler which registers have changed
    // (you don't wanna mess with the compiler's notion
    // which registers mean what)
    END ['eax'];
    
    writeLn('n = ', n, '; m = ', m);
end.

In order to maintain portability between platforms (i.e. your code still compiles for many targets), while optimizing for specific targets, you want to set up conditional compilation:

pascal
program sign(input, output, stderr);

type
    signumCodomain = -1..1;

{ returns the sign of an integer }
function signum({$ifNDef CPUx86_64} const {$endIf} x: longint): signumCodomain;
{$ifDef CPUx86_64} // ============= optimized implementation
assembler;
{$asmMode intel}
asm// ensure result is not wrong// due to any residue// x ≟ 0// al ≔ ¬ZF// propagate sign-bit through reg.// if SF then rax ≔ −1
    xor rax, rax                  // ensure result is not wrong
                                  // due to any residue
    
    test x, x                     // x ≟ 0
    setnz al                      // al ≔ ¬ZF
    
    sar x, 63                     // propagate sign-bit through reg.
    cmovs rax, x                  // if SF then rax ≔ −1
END;
{$else} // ========================== default implementation
begin
    // This is what math.sign virtually does.
    // The compiled code requires _two_ cmp instructions, though. 
    if x > 0 then
    begin
        signum := 1;
    end
    else if x < 0 then
    begin
        signum := -1;
    end
    else
    begin
        signum := 0;
    end;
end;
{$endIf}

// M A I N =================================================
var
    x: longint;
begin
    readLn(x);
    writeLn(signum(x));
end.

As you can see, you can implement whole routines in assembly language, by adding the assembler modifier and writing asm instead of begin for the implementation block.

see also

general

relevant compiler directives

special tasks


From the Free Pascal wiki, page "Asm", as it stood on 2021-02-05 after a change by Kai Burghardt, out of the wiki's dump of 2024-05-26. Copyright stays with the author who wrote it, according to the old wiki's Licensing page. If you have concerns about this material, message the admin.

Revision 1, last changed by WikiArchive .

Talk about this page

Nobody has opened a bench for this page yet. Sign in to open one.