Difference between revisions of "Asm"

From Lazarus wiki
Jump to navigationJump to search
(changed example with Label and optimized it)
 
(7 intermediate revisions by the same user not shown)
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|reserved word]] <syntaxhighlight lang="pascal" inline>asm</syntaxhighlight> starts a [[Frame|frame]] of inline [[Assembly language|assembly]] code.
  
<syntaxhighlight>program asmDemo(input, output, stderr);
+
<syntaxhighlight lang="pascal" 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 highlight="8,21,38">program sign(input, output, stderr);
  
 
type
 
type
Line 41: Line 41:
  
 
{ returns the sign of an integer }
 
{ returns the sign of an integer }
function signum(const x: longint): signumCodomain;
+
function signum({$ifNDef CPUx86_64} const {$endIf} x: longint): signumCodomain;
{$ifdef CPUx86_64} // ============= optimized implementation
+
{$ifDef CPUx86_64} // ============= optimized implementation
 
assembler;
 
assembler;
 
{$asmMode intel}
 
{$asmMode intel}
 
asm
 
asm
// load constants: cmov cannot handle immediates
+
xor rax, rax                  // ensure result is not wrong
// xor-instruction modifies flags => put it prior test
+
                              // due to any residue
xor  r8,  r8 // r8 := 0
 
 
 
// comparison pulled up front for pipelining
+
test x, x                     // x 0
test x,   x // x = 0 ?
+
setnz al                      // al ≔ ¬ZF
 
 
// load constants, since cmov cannot handle immediates
+
sar x, 63                    // propagate sign-bit through reg.
mov  r9, -1  // r9 := -1
+
cmovs rax, x                 // if SF then rax ≔ −1
 
// determine result
 
mov  eax, 1  // result := 1
 
cmovl eax, r9 // if x < 0 then result := -1
 
cmove eax, r8 // if x = 0 then result := 0
 
 
end;
 
end;
 
{$else} // ========================== default implementation
 
{$else} // ========================== default implementation
 
begin
 
begin
// This is what virtually math.sign does.
+
// This is what math.sign virtually does.
 
// The compiled code requires _two_ cmp instructions, though.  
 
// The compiled code requires _two_ cmp instructions, though.  
 
if x > 0 then
 
if x > 0 then
Line 78: Line 72:
 
end;
 
end;
 
end;
 
end;
{$endif}
+
{$endIf}
  
 
// M A I N =================================================
 
// M A I N =================================================
Line 87: Line 81:
 
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" inline>assembler</syntaxhighlight> modifier and writing <syntaxhighlight lang="pascal" inline>asm</syntaxhighlight> instead of <syntaxhighlight lang="pascal" inline>begin</syntaxhighlight> for the implementation block.
  
  
 
== see also ==
 
== see also ==
 
 
general
 
general
 
* [[The inline assembler parser]]
 
* [[The inline assembler parser]]
 
* [[Lazarus inline assembler]]
 
* [[Lazarus inline assembler]]
* [[Label|<code>label</code>]]
+
* [[Label#assembler|<syntaxhighlight lang="pascal" inline>label</syntaxhighlight> § “assembler”]]
  
 
relevant compiler directives
 
relevant compiler directives
* [[sAsmmode|<code>$asmMode</code>]]
+
* [[$asmMode|<syntaxhighlight lang="pascal" inline>{$asmMode}</syntaxhighlight>]]
* [[sGoto|<code>$goto</code>]]
+
* [[$goto|<syntaxhighlight lang="pascal" inline>{$goto}</syntaxhighlight>]]
* [[sStackFrames|<code>$stackframes</code>]]
+
* [[$stackFrames|<syntaxhighlight lang="pascal" inline>{$stackframes}</syntaxhighlight>]]
  
 
special tasks
 
special tasks
Line 106: Line 99:
 
* [[AVR Programming|AVR programming]]
 
* [[AVR Programming|AVR programming]]
  
 +
[[Category:Code]]
 
[[Category:Reserved words]]
 
[[Category:Reserved words]]

Latest revision as of 15:55, 5 February 2021

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

The reserved word asm starts a frame 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({$ifNDef CPUx86_64} const {$endIf} x: longint): signumCodomain;
 8{$ifDef CPUx86_64} // ============= optimized implementation
 9assembler;
10{$asmMode intel}
11asm
12	xor rax, rax                  // ensure result is not wrong
13	                              // due to any residue
14	
15	test x, x                     // x ≟ 0
16	setnz al                      // al ≔ ¬ZF
17	
18	sar x, 63                     // propagate sign-bit through reg.
19	cmovs rax, x                  // if SF then rax ≔ −1
20end;
21{$else} // ========================== default implementation
22begin
23	// This is what math.sign virtually does.
24	// The compiled code requires _two_ cmp instructions, though. 
25	if x > 0 then
26	begin
27		signum := 1;
28	end
29	else if x < 0 then
30	begin
31		signum := -1;
32	end
33	else
34	begin
35		signum := 0;
36	end;
37end;
38{$endIf}
39
40// M A I N =================================================
41var
42	x: longint;
43begin
44	readLn(x);
45	writeLn(signum(x));
46end.

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