Difference between revisions of "Asm"
From Lazarus wiki
Jump to navigationJump to searchm (tc) |
(Frame) |
||
(12 intermediate revisions by the same user not shown) | |||
Line 1: | Line 1: | ||
{{Asm}} | {{Asm}} | ||
− | The reserved word < | + | 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 | + | <syntaxhighlight lang="pascal" line highlight="8,21,38">program sign(input, output, stderr); |
− | { | + | type |
− | function | + | signumCodomain = -1..1; |
− | {$ | + | |
− | + | { returns the sign of an integer } | |
+ | function signum({$ifNDef CPUx86_64} const {$endIf} x: longint): signumCodomain; | ||
+ | {$ifDef CPUx86_64} // ============= optimized implementation | ||
assembler; | assembler; | ||
− | |||
− | |||
− | |||
− | |||
− | |||
{$asmMode intel} | {$asmMode intel} | ||
asm | asm | ||
− | + | xor rax, rax // ensure result is not wrong | |
− | + | // due to any residue | |
− | |||
− | |||
− | |||
− | |||
− | |||
− | // | + | test x, x // x ≟ 0 |
− | + | setnz al // al ≔ ¬ZF | |
− | // | + | |
− | // | + | sar x, 63 // propagate sign-bit through reg. |
+ | cmovs rax, x // if SF then rax ≔ −1 | ||
end; | end; | ||
{$else} // ========================== default implementation | {$else} // ========================== default implementation | ||
− | |||
− | |||
− | |||
begin | begin | ||
− | + | // This is what math.sign virtually does. | |
− | + | // The compiled code requires _two_ cmp instructions, though. | |
+ | if x > 0 then | ||
+ | begin | ||
+ | signum := 1; | ||
+ | end | ||
+ | else if x < 0 then | ||
begin | begin | ||
− | + | signum := -1; | |
− | end | + | end |
− | + | else | |
+ | begin | ||
+ | signum := 0; | ||
+ | end; | ||
end; | end; | ||
− | {$ | + | {$endIf} |
// M A I N ================================================= | // M A I N ================================================= | ||
var | var | ||
− | + | x: longint; | |
begin | begin | ||
− | readLn( | + | readLn(x); |
− | writeLn( | + | writeLn(signum(x)); |
end.</syntaxhighlight> | end.</syntaxhighlight> | ||
− | As you can see, you can implement whole routines in assembly language, by adding the < | + | 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#assembler|<syntaxhighlight lang="pascal" inline>label</syntaxhighlight> § “assembler”]] | ||
relevant compiler directives | relevant compiler directives | ||
− | * [[ | + | * [[$asmMode|<syntaxhighlight lang="pascal" inline>{$asmMode}</syntaxhighlight>]] |
− | * [[ | + | * [[$goto|<syntaxhighlight lang="pascal" inline>{$goto}</syntaxhighlight>]] |
− | * [[ | + | * [[$stackFrames|<syntaxhighlight lang="pascal" inline>{$stackframes}</syntaxhighlight>]] |
special tasks | special tasks | ||
− | * [[Hardware access]] | + | * [[Hardware Access|hardware access]] |
+ | * [[AVR Programming|AVR programming]] | ||
+ | [[Category:Code]] | ||
[[Category:Reserved words]] | [[Category:Reserved words]] |
Latest revision as of 16: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