Asm/fi
From Lazarus wiki
Jump to navigationJump to search
│
Deutsch (de) │
English (en) │
español (es) │
suomi (fi) │
Varattu sana asm
aloittaa lohkon sisäiselle assembly koodille.
program asmDemo(input, output, stderr);
// The $asmMode directive informs the compiler
// which syntax is used in asm-blocks.
// Alternatives are 'att' (AT&T syntax) and 'direct'.
{$asmMode intel}
var
n, m: longint;
begin
n := 42;
m := -7;
writeLn('n = ', n, '; m = ', m);
// instead of declaring another temporary variable
// and writing "tmp := n; n := m; m := tmp;":
asm
mov eax, n // eax := n
// xchg can only operate at most on one memory address
xchg eax, m // swaps values in eax and at m
mov n, eax // n := eax (holding the former m value)
// an array of strings after the asm-block closing 'end'
// tells the compiler which registers have changed
// (you don't wanna mess with the compiler's notion
// which registers mean what)
end ['eax'];
writeLn('n = ', n, '; m = ', m);
end.
Jotta saataisiin siirrettävyys eri alustojen välillä (eli koodi voitaisiin edelleen koota moniin ympäristöihin), samalla kun halutaan optimoida tiettyjä laitteita, niin asetetaan ehdollinen kääntäminen:
program sign(input, output, stderr);
type
signumCodomain = -1..1;
{ returns the sign of an integer }
function signum(const x: longint): signumCodomain;
{$ifdef CPUx86_64} // ============= optimized implementation
assembler;
{$asmMode intel}
asm
// load constants: cmov cannot handle immediates
// xor-instruction modifies flags => put it prior test
xor r8, r8 // r8 := 0
// comparison pulled up front for pipelining
test x, x // x = 0 ?
// load constants, since cmov cannot handle immediates
mov r9, -1 // r9 := -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;
{$else} // ========================== default implementation
begin
// This is what virtually math.sign does.
// The compiled code requires _two_ cmp instructions, though.
if x > 0 then
begin
signum := 1;
end
else if x < 0 then
begin
signum := -1;
end
else
begin
signum := 0;
end;
end;
{$endif}
// M A I N =================================================
var
x: longint;
begin
readLn(x);
writeLn(signum(x));
end.
Kuten nähdään niin voidaan toteuttaa kokonaisia rutiineja assembly kielellä lisäämällä assembler
modifioija ja kirjoittamalla asm
sen sijaan, että se aloitettaisiin
begin
toteutuslohkolla.
Katso myös
Yleistä
Merkitykselliset kääntäjänohjeet
Erityistehtävät