Asm

From Free Pascal wiki

Deutsch (de) English (en) español (es) suomi (fi)

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

 1 program 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 
 8 var
 9 	n, m: longint;
10 begin
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);
29 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:

 1 program sign(input, output, stderr);
 2 
 3 type
 4 	signumCodomain = -1..1;
 5 
 6 { returns the sign of an integer }
 7 function signum(const x: longint): signumCodomain;
 8 {$ifdef CPUx86_64} // ============= optimized implementation
 9 assembler;
10 {$asmMode intel}
11 asm
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
26 end;
27 {$else} // ========================== default implementation
28 begin
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;
43 end;
44 {$endif}
45 
46 // M A I N =================================================
47 var
48 	x: longint;
49 begin
50 	readLn(x);
51 	writeLn(signum(x));
52 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