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