Difference between revisions of "Label"

From Free Pascal wiki
Jump to navigationJump to search
m (formatting)
(changed example with Asm)
Line 4: Line 4:
  
 
A <code>label</code> section is also required for jump targets in [[Asm|<code>asm</code>-blocks]].
 
A <code>label</code> section is also required for jump targets in [[Asm|<code>asm</code>-blocks]].
<syntaxhighlight>program sign(input, output, stderr);
 
  
type
+
<syntaxhighlight>program sumExample(input, output, stderr);
signumCodomain = -1..1;
 
  
{ returns the sign of an integer }
+
{ iteratively calculates the sum over first n integers }
function signum(const x: longint): signumCodomain;
+
function iterativeSumFirstNIntegers(const n: longword): qword;
{$ifdef CPUx86_64}
+
{$ifdef CPUX86_64} // ============= optimized implementation
 +
// assembler modifier appended to routine declaration
 
assembler;
 
assembler;
 +
// you have to familiarize the compiler with symbols
 +
// which are meant to be jump targets
 
{$goto on}
 
{$goto on}
 
label
 
label
signum_done;
+
isfni_iterate;
 
{$asmMode intel}
 
{$asmMode intel}
 
asm
 
asm
mov @result, // result := 1
+
xor rax, rax // rax := 0
cmp x, 0        // x = 0 ?
+
// ecx is used as counter by loop instruction
jg signum_done  // if x > 0 then goto signum_done
+
mov ecx, n  // ecx := n
mov @result, -1 // result := -1
+
isfni_iterate:
jl signum_done // if x < 0 then goto signum_done
+
add rax, qword(ecx) // rax := rax + ecx
mov @result, // result := 0
+
loop isfni_iterate // dec(ecx)
signum_done:
+
// if ecx <> 0 then goto isfni_iterate
 +
 +
// the @result macro represents the functions return value
 +
mov @result, rax // result := rax
 +
// note, a list of modified registers (here ['rax', 'ecx'])
 +
//      is ignored for pure assembler routines
 
end;
 
end;
{$else}
+
{$else} // ========================== default implementation
 +
var
 +
i: longword;
 +
x: qword;
 
begin
 
begin
// This is what virtually math.sign does.
+
x := 0; // mov rax, 0
// The compiled code requires _two_ cmp instructions, though.
+
for i := n downto 1 do // mov ecx, n
if x > 0 then
 
 
begin
 
begin
signum := 1;
+
x := x + i; // add rax, ecx
end
+
end; // loop isfni_iterate
else if x < 0 then
+
iterativeSumFirstNIntegers := x; // mov @result, rax
begin
 
signum := -1;
 
end
 
else
 
begin
 
signum := 0;
 
end;
 
 
end;
 
end;
 
{$endif}
 
{$endif}
  
 +
// M A I N =================================================
 
var
 
var
x: longint;
+
n: longword;
 
begin
 
begin
readLn(x);
+
readLn(n);
writeLn(signum(x));
+
writeLn(iterativeSumFirstNIntegers(n));
 
end.</syntaxhighlight>
 
end.</syntaxhighlight>
 +
Of course in a production program, you would use an algorithm applying the formula <code>sum := (n * (n + 1)) div 2</code> (“Gaussian sum formula”).
 +
 +
  
 
[[category:Pascal]]
 
[[category:Pascal]]
 
[[Category:Control Structures]]
 
[[Category:Control Structures]]

Revision as of 17:05, 8 February 2018

Deutsch (de) English (en) français (fr) русский (ru)

The label keyword is used for declaration of labels (markers for unconditional jumps using goto keyword) used further in the unit/program.

A label section is also required for jump targets in asm-blocks.

program sumExample(input, output, stderr);

{ iteratively calculates the sum over first n integers }
function iterativeSumFirstNIntegers(const n: longword): qword;
{$ifdef CPUX86_64} // ============= optimized implementation
// assembler modifier appended to routine declaration
assembler;
// you have to familiarize the compiler with symbols
// which are meant to be jump targets
{$goto on}
label
	isfni_iterate;
{$asmMode intel}
asm
	xor rax, rax // rax := 0
	// ecx is used as counter by loop instruction
	mov ecx, n   // ecx := n
isfni_iterate:
	add rax, qword(ecx) // rax := rax + ecx
	loop isfni_iterate  // dec(ecx)
	// if ecx <> 0 then goto isfni_iterate
	
	// the @result macro represents the functions return value
	mov @result, rax // result := rax
// note, a list of modified registers (here ['rax', 'ecx'])
//       is ignored for pure assembler routines
end;
{$else} // ========================== default implementation
var
	i: longword;
	x: qword;
begin
	x := 0; // mov rax, 0
	for i := n downto 1 do // mov ecx, n
	begin
		x := x + i; // add rax, ecx
	end; // loop isfni_iterate
	iterativeSumFirstNIntegers := x; // mov @result, rax
end;
{$endif}

// M A I N =================================================
var
	n: longword;
begin
	readLn(n);
	writeLn(iterativeSumFirstNIntegers(n));
end.

Of course in a production program, you would use an algorithm applying the formula sum := (n * (n + 1)) div 2 (“Gaussian sum formula”).