Label

From Free Pascal wiki

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.

Pascal

To declare a label (not defining it) label starts a section with (comma separated) identifiers:

1 program labelDemo(input, output, stderr);
2 
3 {$goto on}
4 // familiarize the compiler with symbols
5 // that are meant as 'goto' targets
6 label
7 	// the symbol 'done' becomes of "type" label
8 	done;

You then define the label, that means associating a symbol with a statement and effectively in the compiled code with an address, by writing the previously declared label in a statement block followed by a colon:

 9 var
10 	n: qword;
11 	x, sum, arithmeticMean: real;
12 begin
13 	n := 0;
14 	sum := 0;
15 	while true do
16 	begin
17 		readLn(x);
18 		if x < 0 then
19 		begin
20 			// leave loop and continue at 'done'
21 			goto done;
22 		end;
23 		sum := sum + x;
24 		inc(n);
25 	end;
26 done:
27 	arithmeticMean := sum / n;
28 	writeLn('arithemetic mean = ', arithmeticMean);
29 end.

Pascal imposes further restrictions on labels: Labels have to be associated with statements: Putting a label right before an end is not allowed. To bypass that, you can insert an empty instruction ; right after the label definition.

In addition to normal identfiers, labels may be non-negative integers.

assembler

A label section is also required for jump targets in asm-blocks, unless the @-address-operator is used.

 1 program sumExample(input, output, stderr);
 2 
 3 { iteratively calculates the sum over first n integers }
 4 function iterativeSumFirstNIntegers(const n: longword): qword;
 5 {$ifdef CPUX86_64} // ============= optimized implementation
 6 // assembler modifier appended to routine declaration
 7 assembler;
 8 // you have to familiarize the compiler with symbols
 9 // which are meant to be jump targets
10 {$goto on}
11 label
12 	isfni_iterate;
13 {$asmMode intel}
14 asm
15 	xor rax, rax // rax := 0
16 	// ecx is used as counter by loop instruction
17 	mov ecx, n   // ecx := n
18 isfni_iterate:
19 	add rax, qword(ecx) // rax := rax + ecx
20 	loop isfni_iterate  // dec(ecx)
21 	// if ecx <> 0 then goto isfni_iterate
22 	
23 	// the @result macro represents the functions return value
24 	mov @result, rax // result := rax
25 // note, a list of modified registers (here ['rax', 'ecx'])
26 //       is ignored for pure assembler routines
27 end;
28 {$else} // ========================== default implementation
29 var
30 	i: longword;
31 	x: qword;
32 begin
33 	x := 0; // mov rax, 0
34 	for i := n downto 1 do // mov ecx, n
35 	begin
36 		x := x + i; // add rax, ecx
37 	end; // loop isfni_iterate
38 	iterativeSumFirstNIntegers := x; // mov @result, rax
39 end;
40 {$endif}
41 
42 // M A I N =================================================
43 var
44 	n: longword;
45 begin
46 	readLn(n);
47 	writeLn(iterativeSumFirstNIntegers(n));
48 end.

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

see also