Difference between revisions of "Asm"

From Lazarus wiki
Jump to navigationJump to search
(changed example with Label and optimized it)
(more colorful syntax highlight)
Line 1: Line 1:
 
{{Asm}}
 
{{Asm}}
  
The reserved word <code>asm</code> starts a [[Block|block]] of inline [[Assembly language|assembly]] code.
+
The reserved word <syntaxhighlight lang="pascal" enclose="none">asm</syntaxhighlight> starts a [[Block|block]] of inline [[Assembly language|assembly]] code.
  
<syntaxhighlight>program asmDemo(input, output, stderr);
+
<syntaxhighlight lang="pascal" start="0" line highlight="3-6,17,22-26">program asmDemo(input, output, stderr);
  
 
// The $asmMode directive informs the compiler
 
// The $asmMode directive informs the compiler
Line 35: Line 35:
 
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|conditional compilation]]:
 
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|conditional compilation]]:
  
<syntaxhighlight>program sign(input, output, stderr);
+
<syntaxhighlight lang="pascal" line start="0" highlight="8,27,44">program sign(input, output, stderr);
  
 
type
 
type
Line 87: Line 87:
 
writeLn(signum(x));
 
writeLn(signum(x));
 
end.</syntaxhighlight>
 
end.</syntaxhighlight>
As you can see, you can implement whole routines in assembly language, by adding the <code>assembler</code> modifier and writing <code>asm</code> instead of <code>begin</code> for the implementation block.
+
As you can see, you can implement whole routines in assembly language, by adding the <syntaxhighlight lang="pascal" enclose="none">assembler</syntaxhighlight> modifier and writing <syntaxhighlight lang="pascal" enclose="none">asm</syntaxhighlight> instead of <syntaxhighlight lang="pascal" enclose="none">begin</syntaxhighlight> for the implementation block.
  
  
Line 95: Line 95:
 
* [[The inline assembler parser]]
 
* [[The inline assembler parser]]
 
* [[Lazarus inline assembler]]
 
* [[Lazarus inline assembler]]
* [[Label|<code>label</code>]]
+
* [[Label|<syntaxhighlight lang="pascal" enclose="none">label</syntaxhighlight>]]
  
 
relevant compiler directives
 
relevant compiler directives

Revision as of 17:28, 11 February 2018

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

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

 0program asmDemo(input, output, stderr);
 1
 2// The $asmMode directive informs the compiler
 3// which syntax is used in asm-blocks.
 4// Alternatives are 'att' (AT&T syntax) and 'direct'.
 5{$asmMode intel}
 6
 7var
 8	n, m: longint;
 9begin
10	n := 42;
11	m := -7;
12	writeLn('n = ', n, '; m = ', m);
13	
14	// instead of declaring another temporary variable
15	// and writing "tmp := n; n := m; m := tmp;":
16	asm
17		mov eax, n  // eax := n
18		// xchg can only operate at most on one memory address
19		xchg eax, m // swaps values in eax and at m
20		mov n, eax  // n := eax (holding the former m value)
21	// an array of strings after the asm-block closing 'end'
22	// tells the compiler which registers have changed
23	// (you don't wanna mess with the compiler's notion
24	// which registers mean what)
25	end ['eax'];
26	
27	writeLn('n = ', n, '; m = ', m);
28end.

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:

 0program sign(input, output, stderr);
 1
 2type
 3	signumCodomain = -1..1;
 4
 5{ returns the sign of an integer }
 6function signum(const x: longint): signumCodomain;
 7{$ifdef CPUx86_64} // ============= optimized implementation
 8assembler;
 9{$asmMode intel}
10asm
11	// load constants: cmov cannot handle immediates
12	// xor-instruction modifies flags => put it prior test
13	xor   r8,  r8 // r8 := 0
14	
15	// comparison pulled up front for pipelining
16	test  x,   x  // x = 0 ?
17	
18	// load constants, since cmov cannot handle immediates
19	mov   r9, -1  // r9 := -1
20	
21	// determine result
22	mov   eax, 1  // result := 1
23	cmovl eax, r9 // if x < 0 then result := -1
24	cmove eax, r8 // if x = 0 then result := 0
25end;
26{$else} // ========================== default implementation
27begin
28	// This is what virtually math.sign does.
29	// The compiled code requires _two_ cmp instructions, though. 
30	if x > 0 then
31	begin
32		signum := 1;
33	end
34	else if x < 0 then
35	begin
36		signum := -1;
37	end
38	else
39	begin
40		signum := 0;
41	end;
42end;
43{$endif}
44
45// M A I N =================================================
46var
47	x: longint;
48begin
49	readLn(x);
50	writeLn(signum(x));
51end.

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