Asm
From Lazarus wiki
Revision as of 17:40, 11 April 2018 by Kai Burghardt (talk | contribs) (ordinal numbers in syntaxhighlight)
│
Deutsch (de) │
English (en) │
español (es) │
suomi (fi) │
The reserved word asm
starts a block of inline assembly code.
1program asmDemo(input, output, stderr);
2
3// The $asmMode directive informs the compiler
4// which syntax is used in asm-blocks.
5// Alternatives are 'att' (AT&T syntax) and 'direct'.
6{$asmMode intel}
7
8var
9 n, m: longint;
10begin
11 n := 42;
12 m := -7;
13 writeLn('n = ', n, '; m = ', m);
14
15 // instead of declaring another temporary variable
16 // and writing "tmp := n; n := m; m := tmp;":
17 asm
18 mov eax, n // eax := n
19 // xchg can only operate at most on one memory address
20 xchg eax, m // swaps values in eax and at m
21 mov n, eax // n := eax (holding the former m value)
22 // an array of strings after the asm-block closing 'end'
23 // tells the compiler which registers have changed
24 // (you don't wanna mess with the compiler's notion
25 // which registers mean what)
26 end ['eax'];
27
28 writeLn('n = ', n, '; m = ', m);
29end.
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:
1program sign(input, output, stderr);
2
3type
4 signumCodomain = -1..1;
5
6{ returns the sign of an integer }
7function signum(const x: longint): signumCodomain;
8{$ifdef CPUx86_64} // ============= optimized implementation
9assembler;
10{$asmMode intel}
11asm
12 // load constants: cmov cannot handle immediates
13 // xor-instruction modifies flags => put it prior test
14 xor r8, r8 // r8 := 0
15
16 // comparison pulled up front for pipelining
17 test x, x // x = 0 ?
18
19 // load constants, since cmov cannot handle immediates
20 mov r9, -1 // r9 := -1
21
22 // determine result
23 mov eax, 1 // result := 1
24 cmovl eax, r9 // if x < 0 then result := -1
25 cmove eax, r8 // if x = 0 then result := 0
26end;
27{$else} // ========================== default implementation
28begin
29 // This is what virtually math.sign does.
30 // The compiled code requires _two_ cmp instructions, though.
31 if x > 0 then
32 begin
33 signum := 1;
34 end
35 else if x < 0 then
36 begin
37 signum := -1;
38 end
39 else
40 begin
41 signum := 0;
42 end;
43end;
44{$endif}
45
46// M A I N =================================================
47var
48 x: longint;
49begin
50 readLn(x);
51 writeLn(signum(x));
52end.
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