Difference between revisions of "Asm"
From Free Pascal wiki
Jump to navigationJump to searchm (things) |
m (wording) |
||
Line 26: | Line 26: | ||
// an array of strings after the asm-block closing 'end' | // an array of strings after the asm-block closing 'end' | ||
// tells the compiler which registers have changed | // tells the compiler which registers have changed | ||
− | // (you don't wanna mess with the compiler's | + | // (you don't wanna mess with the compiler's notion |
// which registers mean what) | // which registers mean what) | ||
end ['eax']; | end ['eax']; |
Revision as of 17:48, 1 February 2018
│
Deutsch (de) │
English (en) │
español (es) │
suomi (fi) │
The reserved word asm
starts a block of inline assembly code.
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
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:
program sumExample(input, output, stderr);
{ iteratively calculates the sum over first n integers }
function iterativeSumFirstNIntegers(const n: longword): qword;
{$ifdef CPUX86_64} // ============= optimized implementation
// assembler modifier appended to routine declaration
assembler;
{$asmMode intel}
label
isfni_iterate;
asm
// ecx is used as counter by loop instruction
mov ecx, n // ecx := n
mov rax, 0 // rax := 0
isfni_iterate:
add rax, ecx // rax := rax + ecx
loop isfni_iterate // dec(ecx)
// if ecx <> 0 then goto isfni_iterate
// the @result macro represents the functions return value
mov @result, rax
// note, a list of modified registers (here ['rax', 'ecx'])
// is ignored for pure assembler routines
end;
{$else} // ========================== default implementation
var
i: word;
x: qword;
begin
x := 0; // mov rax, 0
for i := n downto 1 do // mov ecx, n
begin
x := x + i; // add rax, ecx
end; // loop isfni_iterate
iterativeSumFirstNIntegers := x; // mov @result, rax
end;
{$endif}
// M A I N =================================================
var
n: longword;
begin
readLn(n);
writeLn(iterativeSumFirstNIntegers(n));
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.
Of course in a production program, you would use an algorithm applying the formula sum := (n * (n + 1)) div 2
(“Gaussian sum formula”).
see also
general
relevant compiler directives
special tasks