You are on page 1of 65

Pépé le Manual

Version 1.11

by Philippe Guillot
pguillot@gmail.com

Pépé le compiler is a freeware standard Pascal compiler for the Android platform, that
runs directly on the handheld. Pépé generates true native ARM executable code from
standard Pascal source program.
Console applications can be generated on board in the train, while waiting the bus, while
fishing, on the beach, or what ever you are, even offline, either on a tablet or on a
smartphone, provided it runs with the Android operating system and with an ARM
processor.
The name of the story. This compiler has first been developed for the PalmOS platform,
generating on board true 68 000 native code. The name of this application was PP for
« Palm Pascal » and to be pronounced « Pépé » with the french accent.
When Palm devices migrated to the ARM processor, a new version of this compiler,
generating true ARM native code was developed.
Pépé le compiler is the successor of these two compilers, and the name suggests that it still
allows to program Pascal in the palm of the hand.
And voilà.

1/65
2/65
Le user manual
Installation. To install Pépé le compiler just copy the “Pepe.apk” file on the external
memory of the device, and launch it by using the “File” application.
User manual. When the application is launched, a list of files appears.

Files recognized by Pépé le compiler are :


• Pascal source files, with the extension “.pas”, “.p” and “.pp” insensitively to the case.
• Executable files, with the extension « .exe »
The menu allows to
• New source file : create a new source file.
• Storage : Choose the default memory location internal or external (see further). By
default, the external location is set.
• Info : displays the about box.
A short click on a source file compiles it and builds the executable.
A short click on an executable file runs it.
A long click displays a context menu. This context menu depends on the type of the file.
On a source file, the context menu allows to :
• edit : launch the editor in order to edit the file
• build : compiles the file and builds the executable. This is equivalent to a short click
on the file name.
On an executable file, the context menu allows to :

3/65
• inspect : launch a disassembler to show the generated ARM instructions.

• run : execute the file. This is equivalent to a short click on the file name.

4/65
On all files :
• The delete context menu item deletes the selected file.
• The rename context menu item opens a dialog in order to give a new name to the
file.
• The edit context menu launch the editor.
The source files may be stored either, by default in the external memory (sdcard) or in the
internal memory.
The external memory is in the directory /mnt/sdcard/Pepe/.
The internal memory is in the directory /data/data/pp.compiler/, which is the
internal storage location of the Pépé application.
The executable files are always stored in the internal memory, as this is the only location
that may be mapped as executable zone.
Under the source editor, the menu is :
• Build : launch the compiler to create the executable file.
• Save : save the current file.
• New : initialize the editor with a new source file.
• Font size : choose the font size for both the editor and the console.
At the end of a successful compilation, a dialog box with three buttons appears :
• Done : stays in the console
• Edit : launches the editor with the latest compiled source file.
• Run : launches the generated executable to run the compiled program.

5/65
The programs are executed in a console that allows all the features of the Standard Pascal.
On compilation error, a dialog appears with the error message, and the Done button
launches the editor on error position.

6/65
The compiler stops on the first compilation error.

Program execution. Programs can be executed either from the file browser or from the
dialog that appears after the compilation. The programs are executed in an execution
console.
At the end of the program execution, a dialog appears, informing the user that the
execution is completed, and eventually on the error that has been encountered during the
execution. This dialog has two buttons :
• done to erase the dialog and return to the execution console. From the execution
console, hiting the back arrow returns either in the editor or in the file browser
depending if the execution has been launched after the compilation dialog or from
the file browser.
• edit to return the editor if the program has been launched after a compilation, or
return to return to the file browser if the program has been launched from the
browser.

7/65
8/65
Le language characteristic
The language syntax is mostly compliant to the Standard Pascal ISO 7185:1990 level 1.
Documentation on this standard may be found at moorecad.com/standardpascal
In particular, it supports:
• non local goto,
• procedural and functional parameters,
• standard syntax for new and dispose for pointer to record with variant.
In addition, the language supports some Turbo Pascal extensions such as strings, @
operator, bitwise operators, etc.
The program name in the program header defines the file name of the created executable
file.
program Minimal;
begin
end.

The compilation creates an executable file "Minimal.exe" in the internal storage location.

Non standard and implementation defined features


In this section, are presented the main non standard features implemented for
convenience.

There is no run time overflow control nor range check.


type days=(mon,tue,wed,thu,fri,sat,sun);
var d : day;
begin
d:=sun;
d:=succ(d); // does not generate compilation error
end;

Order of the declaration. In the declaration section of a block, the constants, variables,
types, procedures and functions can be declared in any order.
Forward domain type for pointer types must be declared in the same type declaration
block.
The only standard constraint on the order of the declarations is for the labels. The labels
must be declared first, before any other declaration.
Constant precomputation. Most constant expression computable at compilation time are
allowed anywhere a constant is expected.
const
n=5;
nn=2*n;
type
table : array[0..nn-1] of n..3*n;

9/65
Predefined function such as sin, cos, exp, sqrt, log are not precomputed in constant
expression.
Strings. Strings of character can either be defined through the standard definition packed
array[1..n] of char or with the non standard keyword string.
string is equivalent to a packed array[1..255] of char.
string[n] is equivalent to a packed array[1..n] of char. The maximum allowed
value of n is 255.
The first character of a string s, is accessed by s[1].
Strings are implemented with a terminal zero. The assignment of a string copy the source
until the terminal zero only.
The operator + is applicable to string and means the concatenation.
The comparison operators <, >, <=, >=, =, <> apply the lexicographic order.
The predefined function length returns the actual length of a string, which is the number of
characters until the terminal zero.
The string type is compatible with the char type and with any other string type of any
length.
The string type is allowed as the return type of a function.
Hexadecimal notation. The character '$' starts hexadecimal representation of integer.
const mask = $0000ffff;
Comments. The C++ style comments is supported. The characters following // are ignored
until the end of the line.
// this is a comment, ignored by the compiler.

Contrary to the standard Pascal specification, Pascal style comments can be


nested. When several comments are open inside a comment, they all must be
closed.
(* … (* … *) these characters are ignored until the final *)

Identifiers. The underscore character '_' is allowed inside an identifier.


var my_name : string;
Pointer type. A predefined type 'pointer' is assignment compatible with all other pointer
types, with procedural parameters and procedural variables.
Address operator. The address operator @, applied to a variable, a function or a
procedure, returns a pointer equal to the address of the variable.
var
p : pointer;
a : integer;
...
p:=@a;

10/65
When this operator is applied to a var formal parameter of a procedure or a
function, it returns the address of the variable passed as parameter.

Inline attribute. This attribute, following a function or procedure declaration, allows to


insert code in place where the function is called.
When an inline procedure or function is called, the compiler just insert the code, without
any prolog and epilog.
function even(x:integer):boolean; inline($e2000001,$e2200001);
// and r0,r0,#1
// eor r0,r0,#1

Typeless var parameter. Typeless formal parameter are allowed in the header of a
procedure or a function. In this case, any variable is compatible with the actual parameter.
The value passed to the procedure or function is the adress of the actual parameter.

procedure memmove(var dest, src; numbytes : integer);


type bytearray=array[0..1000]of 0..255;
var psrc, pdest : ^bytearray;
i : integer;
begin
psrc:=@src;
pdest:@dest;
for i:=0 to numbytes-1 do pdest^[i]:=psrc^[i];
end;
var a,b : any_type;
begin
memmove(a,b,sizeof(any_type));
...

'Const' keyword in a formal parameter list. The const keyword is allowed in a formal
parameter list. It means that this parameter cannot be modified inside the procedure, and
allows some code optimization.
If the parameter a scalar less that 4 bytes long, then the value of the actual parameter is
passed to the called procedure.
If the parameter is a string, a set or is more than 4 bytes long, then the address of the
actual parameter is passed to the called procedure. This avoid useless copy of the data.
Unsigned integer. A type declared as a subrange of the integer type and with a non
negative lower value is considered as an unsigned integer, for example :
type byte = 0..255;
type shortint = 0..65535;

The value of the division is not the same when they are applied to signed and to unsigned
parameters.
• The signed operator is applied if one of the two parameters is signed.
• The unsigned operator is applied if the two parameters are unsigned.
Shift operators. Additional keywords shl and shr are the usual shift operator. They have

11/65
the same precedence as the multiplication.
Then the first parameter is signed, then, when applying the shr operator, the sign bit is
propagated, such that x shr 1 is the same as x div 2.
Boolean operators applied to integer type. The Boolean operators and, or and xor can
be applied to integer type. In this case, they perform bitwise operations.
Xor operator. Additional keyword xor performs the exclusive or with the same precedence
as or.
Applied to integer type, the xor operator performs bitwise exclusive or.
Applied to set type, the xor operator performs the symmetric difference of the set.
Sizeof function. A predefined function sizeof is applicable to a variable identifier or a
type identifier. It returns a constant equal to the number of bytes of the variable or the
type.
Ordinal value of the enumerated constants. By default, the constants defined in an
enumerated type are the integers starting at zero and incremented by one on each
enumerated constant.
Any integer value may be assigned to these constant, for example :
type DayOfWeek = (mon = 1, tue, wed, fri, sat, sun);
Any integer type value is supported. The values must be declared in increasing order.
The size of an enumerated may be 1, 2 or 4 bytes, depending on the value of the greatest
constant.
type enum = (a=0, b=$ffff, c=$10000); // is 4 byte long
Functions invoked as procedures. If a function has a side effect and if the value is not
required, then it may be invoked like a procedure.
function double(var x : integer):integer;
begin
x:=2*x;
double:=x:
end;
var x : integer;
begin
x:=2;
double(x); // the value is ignored
..

Use of the keyword 'nil' as actual parameter. The keyword 'nil' is allowed as actual
parameter congruent to a 'var' formal parameter, or a 'const' string parameter. In this case,
the value of 'nil' is passed to the procedure.
This allows to define system functions with a pointer parameter and to use the ability of
passing 'nil' if the corresponding parameter is not required for assignment.
Procedural types. Standard Pascal allows procedural parameter. In addition, a procedural
type exists.

12/65
This type is defined as the procedure or function header and by omitting the identifier.
type proctype = procedure(var i : integer);
type functype = function(var c : char): real;
The value or a variable declared of this type is the address of the code to execute to run
this function or procedure. The pointer type is assignment compatible to procedural types.
Default case statement. In a case statement, no error is generated if some case labels are
missing from the selector type.
Moreover, an optional else statement is allowed for other labels
case n of // n is an integer
0 : x:=1;
1 : x:=-1;
else x:=0;
end;
Inline assembler. To get faster and smaller code, it is possible to define a procedure or a
function in the ARM assembly language, with the keyword asm after the procedure header.
function Swap32(x:integer):integer;
asm
eor r1, r0, r0, ror 16
bic r1, r1, $00ff0000
mov r0, r0, ror 8
eor r0, r0, r1, lsr 8
mov pc, lr // return from subroutine
end;
Special use of the keyword nil. The keyword nil is allowed as actual parameter congruent
to a var formal parameter or a const string parameter. In this case, the value of nil is
passed to the procedure.
function zero(var x : integer);
begin
if @x<>nil then x:=0;
end;

zero(nil); // does nothing

This ability is useful for system call that take a pointer parameter and assign a result only if
this pointer is not nil. These system call can be defined in Pascal style with a var parameter.
The value nil can be passed if the parameter is not required.

Environment variables. A predefined variable named environ, declared as pointer is


initialized with the address of the array of strings that defines the system environment
variables.

Typed constants. (from version 1.??) Any file permissible type may be specified in a
constant declaration.

Contrary to Turbo Pascal, typed constant are NOT initialized variables, but are true
constants that cannot be modified.

13/65
const i : integer = 55;
n : string[8]='hello!';
t : array[1..3] of integer = (10,20,30);
r : real = 1; // force constant cast to real type
s : string = 'x'; // force cast char to string type
rec : record lo, hi : integer end = (lo:1; hi:2);
let : set of char = ['a'..'z','A'..'Z'];

14/65
Le Pépé language reference

Symbols, key words and lexical tokens

Characters :
• letters 'a'...'z'.
The Pascal language is not case sensitive. Capital letter have the same significance
as low case letters.
• Digits '0'..'9';
• hexadecimal digits : '0'..'9', 'a'..'f';
• special symbols:
+ - * / = < > [ ] . , ( ) : ; ^ @ { } ' $
Contrary to what the standard specifies, alternative token @ is not a
replacement for ^. It is the address operator.
Moreover, standard alternative tokens (. and .) for [ and ] are not
supported.
• double characters :
<= >= := .. (* *)
• key words : they are reserved word that cannot be redefined.
and array asm begin case const
div do else end for function
goto if in label mod nil
not of or packed procedure program
record repeat set shl shr string
then to type until var while
var xor
• predefined symbols : these symbols are predefined, but are not keyword nor
identifiers.
• Directives
inline forward

• Predefined identifiers
abs arctan boolean char chr close
cos dispose eof eoln exp false
get input integer length ln maxint
new odd ord output pointer pred
put read readln real reset rewrite
round sin sizeof sqr sqrt succ
text true trunc write writeln

15/65
Identifiers
An identifier starts with a letter followed by a sequence of letters, digits, and underscore '_',
that is different form any key word. They serve to identify constant, variables, types,
procedures and functions.
There is no limit for the length of an identifier. It is only bounded by the available memory.
identifier = letter { letter | digit | _ }
Examples: Writeln, print_array, String64

Labels
A label is a nonempty sequence of at most 4 digits. They are used together with the goto
instruction.
Examples: 99, 666, 9999, 0

Numbers
A number is either a signed integer or a signed real.
decimal_number ::= [ + | - ] digit_sequence [ . digit_sequence ] [ e [ + | - ]digit_sequence ]
hexadecimal_number ::= $ hexadecimal_digit [ , hexadecimal_digit ]
digit_sequence ::= digit [ digit ]
digit ::= 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9
hexadecimal_digit ::= 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | a | b | c | d | e | f
A signed integer is represented by an optional sign '+' or '-' followed by either a sequence
of digits.
The sequence of digits may be either a sequence of decimal digits, or the character '$'
followed by a sequence of hexadecimal digits.
Examples: 15, -1000, $aaaa, -$ffffffff, +2011

An integer is internally implemented as a 32 bits word. The range of signed integer is the
interval [−2 31 ,231−1]=[−2147483648,2147482647] . It allows about 16 decimal digits
precision in computations. Results are rounded to the nearest value.
A signed real is represented by an optional sign, a mantissa and an optional exponent. The
mantissa is an integer part, followed by an optional fractional part.
Examples : 13.25e+6, 3.1415926, 1e-30

A real is internally implemented as an IEEE 754 double precision floating point format on 8
bytes (64 bits). Sizeof(real) returns 8.
The minimum positive value is 4.9406564584124654 x 10 −324 (minimum subnormal positive
double).
The maximum positive value is 1.7976931348623157 x 10 308 (maximum double).

16/65
Strings
Literal strings are delimited by quotes. To insert a quote in a string, it must be repeated
once.
const My_mame = 'My name is ''Philippe Guillot''';
// My name is 'Philippe Guillot'

A string must be defined in a single line.


Any editable ascii character is allowed in a string.
Constant string expressions are precomputed, thus a concatenation expression can define
a constant. This allows to insert non editable characters in a string, and to define long
string constants on several lines :
const
// how inserting non editable character in a string ?
two_lines_string = 'first line' + chr(10) + 'second_line';
// how defining a string on several lines ?
string_defined_on_two_lines=
'Philippe'+
'Guillot';

Comments
Section of program between (* and *), and between { and }, are comments not
interpreted by the compiler.
Pépé supports also the C++ style comments. Portions of code after // are ignored until
the end of the line.

The (* ... *) and { ... } can be nested. This is a non standard feature.
(* This start a comment
this is ignored. Any ascii chàractér cañ be üsed
(* This starts a new comment of level 2
*) This only closes the comment opened in the previous
line
This text is still ignored
*) // this closes the main comment.
x:=x+1; // this line is now interpreted by the compiler
// provided it is not embedded in a comment

Program
The Pascal grammar defines a program which is compiled into an executable file that can
be run form the Pépé environment.
program ::= program_header ; block .
program_header::= program identifier [ ( program_parameters ) ]
program_parameters ::= identifier { , identifier }

17/65
The program identifier defines the name of the executable file. The identifier in the
parameter list must be those of a global variable.
program hello(output); // output is a predefined text variable
begin
writeln('Hello wordl!');
end;
A file “hello.exe”, which is recognized as an executable file by the Pépé environment is
created.

Blocks
A block is a text of code delimited by a beginning and an end. It contains declarations and
instructions. It may define a procedure, a function or a program.
All the identifiers and labels declared in a block are local to this block.

Syntax
block ::= declaration_part statement_part
declaration_part ::= label_declaration_part
{ (constant_definition_part | type_definition_part | variable_definition_part |
function_definition_part | procedure_definition_part ) }
statement_part ::= compound_statement

Labels
label_declaration_part ::= [ label label { , label } ; ]
A label is a sequence of 4 decimal digits. The declared label are those used in the
statement part.
label 6, 666, 1234, 99;

Constants
constant_declaration ::= [ const constant_definition ; { constant_definition ; } ]
A constant definition introduces an identifier to denote a value. It defines the constants
usable in the block.
constant_definition ::= identifier [ : type_definition ] = expression
The expression must define constant value which can be evaluated at compilation time.
When the type is not specified, then it is implicitely determined by the expression.
const message = 'hello world !';
n = 22;
m = 1 shl n;

A constant definition may by typed either to specify the type of the expression, or to define
structured, array or record constants.

18/65
Types
type_declaration ::= [ type type_definition ; { type_definition ; } ]
The type determines the values that a variable can take. A type definition introduces an
identifier to denote a type.
type_definition ::== identifier = type_denoter
type_denoter ::= type_identifier | simple_type | pointer_type | structured_type | string_type
A simple type is either a scalar type or the real type.
A structured type may be an array type, a record type, a set type or a file type.
Scalar type. The possible values of a scalar type is a set of ordered values. Each value can
be represented by an integer.
The following scalar types identifier are predefined :
• integer. This identifier denotes integers values. They are internally implemented as
32 bits words, representing signed integers in the range :
-2 147 483 648 .. + 2 147 483 647.
• Boolean. This identifier denotes the Boolean type, which is the enumeration of two
values. The predefined constant identifiers false and true denotes theses values. The
ordinal value of false is 0, and the ordinal value of true is 1.
• char. This identifier denotes the character type, ordered according the ASCII code.
The ordinal value of a character is its ASCII code. The predefined function chr returns
the character that correspond to any given integer value in the range 0..255.
Enumerated type. The enumerated types allow to define sets of ordered values by
enumerating the identifiers that represents those values. The order is those of the
enumerating sequence. The value assigned to an identifier in this list may be specified to a
given value, provided it respects the order.
enumerated_type ::== ( identifier [ = integer ] { , identifier [ = integer ] } )
The identifier that appears in the list is a constant in the block in which it is defined. The
type of this constant is the defined enumerated type. By default, the ordinal value of the
first constant in the list is 0, ant this value is incremented by one on each term of the list,
except if a specified integer value is assigned.
The size of an enumerated type depends on the greatest value :
• One byte for ordinal values up to 255
• Two bytes for ordinal values up to 65 537
• four byes elsewhere.
Examples :
type color = (red, yellow, orange, green, blue, tartan);
card = (club=1, diamond=2, heart=4, spade=8);
event = ( nilevent, openevent, closeevent, invalidevent=$ffff );

19/65
// sizeof(event)=2

Subrange type. The subrange type is a subset of a scalar type between lower bound and
an upper bound. It includes identification of the smallest and the largest value in the
subrange.
subrange_type ::= constant .. constant
The two constants must have the same scalar type, and the lower bound must be less than
or equal to the upper bound.
type byte = 0..255;
hot_color = red..orange;
digit = '0'..'9';

The constants may be any value computable at compilation time.

In the definition of a subrange type, the constant expression must not begin by a
left parenthesis, to distinguish from an enumerated type.

type interval = 2*n .. 3*n; // allowed


const inf = (a-b) div 2;
sup = (a+b) div 2;
type scale = inf .. sup; // necessary

Reals. The predefined identifier real denotes the real type. The values are an
implementation of the IEEE 754 double precision floating point number as described
above. The real type is a simple type.
Arrays. An array is a structured type composed of a fixed number of elements of the same
type.
array_type ::= { packed } array [ index_type { , index_type } ] of type_denoter
index_type ::== scalar_type
The index type defines the number of element of each dimension of the array. Any scalar
type is allowed provided that the memory is large enough to allocate room for a structure
of this size.
type table = array[1..1000] of real;
size = -2..2;
multi_table = array[boolean, boolean, size] of real;
double_table = packed array[1..2] of array [1..4] of boolean;

The standard Pascal keyword packed has no effect.


Strings. Arrays of the form packed array[1..n] of char, where n denotes an
integer is called a string type and has extra properties.
The keyword string allows to define string type.
• The declaration string[n] is equivalent to packed array[1..n] of char.
• The declaration string is equivalent to string[256];
Strings are implemented with C style terminal zero. All characters after the terminal zero
are generally ignored.

20/65
Records. A record is a structure with a fix or variable number of elements, called field, and
denoted by an identifier. The record declaration specify the identifier and the type of each
field.
record_type ::= record field_list end
The field list of a record has two optional parts : a fixed part, and a variant part. The field
list may be empty.
type empty_record = record end;
field_list ::= [ ( fixed_part [ ; variant_part ] | variant_part ) [ ; ] ]
The fixed part is the list of the fixed field. It is defined for each field by the identifier and the type.
fixed_part ::= record_section { ; record_section }
record_section ::= identifier list : type_denoter
type date = record
day : integer;
month : string[12];
year, century : integer;
end;
The variant part allows several field list, called variant, to share the same memory space.
The data can be be accessed by several format.
variant_part ::= case variant_selector of variant { ; variant }
variant_selector ::= [ identifier : ] ordinal_type_identifier
variant ::= constant_list : ( field_list )
constant_list ::= constant [ , constant ]
If the optional identifier in the variant selector is present, then an additional field is defined
with this identifier.
type person =
record
name: string[20];
case citizen : boolean of
true : ( birth_city : string[20] );
false : ( arrival_date : string[10] )
end;
Memory layout of this record :

Citizen Spare birth_city 20 bytes


name, 20 bytes
1 byte 3 bytes arrival_date 10 bytes

The field list in the variant part may also have a variant part.
type
shape = (triangle, rectangle, circle);
polygon = record
area : real;
case shape of
triangle : ( angle1, angle2, angle3 : real);

21/65
rectangle : ( case square : boolean of
false : ( side1, side2 : real)
true : ( side : real)
) ;
circle : (radius : real )
end;
The size of a variable with a variant part is the maximum size for all variants. Moreover, for
dynamic variables, it is possible to allocate memory with only the required size.
All identifiers that denote a field in a record must be different.
Set. A set is a collection of objects, all of the same type, called the base type. The set type
can be seen as a subset of the base type. The base type may be any ordinal type.
set_type ::= set of base_type
base_type ::= ordinal_type
type byte_set = set of 0..255;
A variable of type set can denote the empty set up to the set that contains all the element
of the base type. A set type is equivalent to a packed array of boolean, the value for a given
index is true if it belongs to the set, and false elsewhere.
The ordinal values of the base type must be in the interval 0..255. The size of a set variable
is aligned to a 32 bits words, equal to 4∗ ⌊
m+ 31
32 ⌋
, where m is the upper bound of the
base type.
Files. A file is a linear sequence of element of the same type, called component type. The
component type must be file permissible. It may be any type, except the file type, and a
structured type that contains a file type.
file_type ::= set of component_type
type book = file of char;
The number of element of a file is not determined by the declaration. There exist special
procedures and functions to access to the element of a file.
A predefined text type denote a file of character that are structured by lines.
Pointers. A pointer type defines a variable whose value is the address of another variable.
This latter variable is called the pointee. The variables and the values identifying them are
allowed to be created and destroyed during the execution of the program, which is called
the dynamic allocation.
The keyword nil denotes the null value of all pointer types, with no pointee variable.
pointer_type ::= ^ domain_type | pointer_type_identifier
The base type may be an identifier which is not yet declared, but it must be defined at the
end of the current type declaration.
type plist = ^tlist;
tlist = record
data : integer;

22/65
next : plist;
end;
Variables identified by a pointer may be either created with the predefined procedure new
or defined by the non standard address operator @ applied to an existing variable. The
predefined procedure dispose free the memory previously allocated by a call to new.
A predefined type identifier pointer is defined as a pointer type with no specified domain
type. This pointer type is compatible to any other pointer or procedural type.

Procedural type. Procedures and functions may be declared as variable of procedural


type, with the same syntax as Turbo Pascal.
procedural_type ::= ( procedure [ formal_parameter_list ] ) |
( function [formal_parameter_list] : result_type)

A procedural type has the same syntax as the declaration of procedure or function, with the
identifier omitted.
type
proc_t = procedure;
math_func_t = function(x : real):real;
assign_proc_t = procedure(var dst:integer; val:integer);
Compatible types. Two types T1 and T2 are said to be compatible if either one of these
statements is true :
• Type T1 and type T2 are the same type, for example by a declaration :
type T1=T2;
• Types T1 and type T2 are both string types.
• Type T1 is a subrange of type T2, or type T2 is a subrange of type T1, or both types are
subrange of the same host type.
• Type T1 and type T2 are both pointer types with compatible domain types. The pointer type
with null domain type is compatible with all other pointer types.
• T1 is a pointer type with null domain type and T2 is a procedural type.
• T1 and T2 are either both set types, or both file types, with compatible base types.
• T1 and T2 are both procedural types with congruent parameter list, and same return type.

Assignment compatible. In order to assign a variable of type T2 to a variable of type T1, the type
T2 must be assignment compatible to type T1.
• If T2 and T1 are compatible, then T2 is assignment compatible to T1.
• Any integer type is assignment compatible to a real type.
• The char type is assignment compatible to any string type.

Variables
Variable declaration. A variable declaration is a identifier list that denote the variables and
a type associated to each of these variables.
variable_declaration ::== identifier_list : type_denoter
The type of a variable can be a type identifier previously defined in a type declaration of
the current block, or in a block of higher level. It can also be a new type definition.

23/65
var
a,b,c : real;
i,j : integer;
digit : 0..9;
operator : (plus, minus, times);
matrix : array[0..63,0..63] of real;
c : colour;
f : file of char;
palette : set of colour;
p1,p2 : person;

An identifier specified in the identifier list of a variable declaration is a variable identifier for
all the block where it is defined, and this variable can be used in the whole block, except if
the same identifier is declared in a sub block.
The variables declared in the declaration section of the program are global variables. They
are stored in the global data segment, referenced by register r10.
The variables declared in a procedure or a function are local variables. They are stored in
the stack segment. It is referenced by register r11 which is initialized in the prolog code of
the procedure or function.
Variable reference. A variable reference may be :
• a variable,
• the component of a variable of structured type or a string type,
• a dynamical variable referenced by a pointer type.
variable_reference ::= variable_identifier { qualifier } | function_call ^
The syntax of a variable reference allows a function call that returns a pointer. This latter
becomes a dynamic variable.
program test;
var n : integer;
type pint = ^integer;
function brol(k:integer):pint;
begin
n:=k;
brol:=@n;
end;
begin
writeln(brol(555)^);
end.
Qualifier. A variable access is a variable identifier together with one or several qualifier that
modify the reference meaning.
Qualifier ::= index | field_descriptor | ^
For instance, an array identifier without qualifier, denotes the whole array. But an array
identifier with index qualifier denotes a component of the array.
result
result[i]

24/65
If the component of the array is a field type, it can be qualified by the field descriptor.
result[i].info

If the field descriptor is a pointer or a file, the ^ operator accesses to the data
result[i].info^

Index. The access to the component of an array or a string is performed by a reference to


the array variable followed by the index denoting the component.
index ::== [ expression { , expression } ]
The index expressions select the component for each dimension of the array. The number
of expression cannot be greater that the number of index specified in the array declaration.
The type of the index expressions must be equal to the type declared in the array
declaration.
Component of a multidimensional array can be accessed either by multiple index or by
multiple expression in the same index. The two following variable references are equivalent.
matrix[i][j] // multiple index
matrix[i,j] // multiple expressions in the same index

Field descriptor. The reference to a particular field of a record variable is performed by the
reference to the variable followed by a field descriptor, denoting the required field.
field_descriptor ::= . field_indicator
p2^.mother
result[i].when.month
coord.theta

In a with statement, the field descriptor do not need to be preceded by the field variable
reference that contains them.
Dynamic and buffer variables. The value of a pointer variable is either the keyword nil or
the address of a dynamic variable.
The access to the dynamic variable referenced by a pointer variable, or to the buffer
variable referenced by a file variable, is performed by following the pointer variable
reference with the symbol ^.
p^
p1^.parent^
input^

Predefined variables. Two variables input and output are predefined. They have type text
and represent the standard input from the keyboard, and the standard output on the
console. These variables are initialized and the corresponding text do not require to be
open for inspection nor generation.

25/65
Expressions
An expression is a sequence of operands and operators which returns a result.
Dyadic operators have two operands. The operator is between the operands : a + b
Monadic operators have a single operand. The operator precede the operand : -a, not x
In complex expressions, the operators have the following priority :

Operators Priority Category


not + - First (high priority) Monadic operators
* / div mod and shl shr Second Factor operators
+ - or xor Third Term operators
= <> <= >= in Fourth (low priority) Relation operators

The rules for evaluating an expression according to the operators priority are :
• An operand between two operators with different priority is linked to the operator
with the highest priority.
• An operand between two operators with the same priority is linked to those on the
left, preforming a left to right evaluation.
• Expressions between parenthesis are evaluated first.
Expressions syntax. The priority rules are a consequence of the expression syntax.
factor ::= ( [ @ ] ( variable_access | procedure_identifier | function_identifier ) |
unsigned_constant |
( expression ) |
( not | - | + ) factor |
function_call |
set_constructor
unsigned_constant ::= unsigned_number | character_string | constant_identifier | nil
x // variable reference
@x // pointer to a variable
15.5e22 // unsigned number
sin(x/2) // function call
['0'..'0','a'..'f','A'..'F'] // set constructor
nil // keyword nil
not negative // negate a boolean
Operators applicable to factors are multiplication like operators.
term ::= factor { ( * | / | div | mod | and | shl | shr ) factor }
x*y
z/(1+z)
even or negative
(x<=0) or (x>=10)
Operators applicable to terms are addition like operators.
simple_expression ::= [ - ] term { (+ | - | or | xor ) term }

26/65
x + y
- x
i*j+1
Operators applicable to simple expression are relational operators
expression ::= simple_expression { ( < | > | <= | >= | <> | = | in ) simple_expression }
x=1.5
red in palette
even <> negative
(i<j) = (j>k)

Operators.

Arithmetic expression are evaluated from right to left according to operator


priority. This may be important if the expression are function call with side effects.

program test;
var n : integer;
function foo:integer;
begin
n:=n+2;
foo:=n;
end;
function bar:integer;
begin
n:=n*2;
bar:=n;
end;
begin
n:=1;
writeln(foo+bar); // displays 6
n:=1;
writeln(bar+foo); // displays 9
end.
Dyadic arithmetic operators :

Operator Operation Type of operands Type of result


+ Addition Integer or real
Integer if both operand are integer,
- Subtraction Integer or real
real otherwise
* multiplication Integer or real
/ Division Integer or real real
Div Euclidian division Integer Integer
Mod Euclidian remainder Integer Integer

If both operand are unsigned integers, the result is en unsigned integer. If one of the two
operands is a signed integer, the result is a signed integer.
The division routine is not the same when it operates on signed or on unsigned integers.

27/65
Monadic arithmetic operators :

Operator Operation Type of operand Type of result


+ identity Integer or real
Same type as operand
- negation Integer or real

If the operand of the negation operator is an unsigned integer, the result is a signed
integer.
Logic operators on integers :

Operator Operation Type of operands Type of result


not bitwise complement
and bitwise and
or bitwise or integer integer
xor bitwise xor
shl shift left
shr shift right

The not operator is monadic.


The expression i shr j returns the value obtained by shifting value of i of j bits on the right.
The result is of the same type as i.
Boolean operator :

Operator Operation Type of operands Type of result


not Logical negation
and Logical and
Boolean Boolean
or Logical or
xor Logical exclusive or

Boolean expression are evaluated from left to right and the evaluation stops as
soon as the result is known.

For example, when evaluating the expression a or b, if the result of a is true, then the
expression b is not evaluated, when evaluating the expression a and b, if the result of a is
false, then the expression b is not evaluated.
String operator : The only operator applicable to strings is the concatenation operator,
denoted by +.

Operator operation Type of operator Type of result


+ concatenation String or char string

28/65
full_name:= first_name+' '+second_name'
If the type of the operand is char, it is considered as a single char string. String
implementation being with terminal zero, the character with null ordinal value is equivalent
to the empty string.
Set operators :

Operator Operation Type of operands and result


+ union
- Set difference
Compatible set types
* intersection
xor Symmetric difference

A scalar value x belongs to A+B if it belongs either to A or to B.


A scalar value x belongs to A*B if it belongs to A and to B.
A scalar value x belongs to A-B if it belongs to A, but not to B.
The set type is implemented as a bit field. The bit number x of this bit field is set to one if
the element of ordinal value x belongs to the set.
On this bit field :
• The + operation performs a bitwise or.
• The * operation performs a bitwise and.
• The – operation performs the bitwise operation a and not b.
• the xor operator performs a bitwise exclusive or .
Relational operators :

Operator Operation Type of operands Type of result


= equality Compatible simple types,
<> different pointer, set, string

< Less than


> Greater than Compatible simple types,
<= Less than or equal string

>= Greater than or equal Boolean


<= subset
Compatible sets
>= contains
in Belongs to Left operand : any scalar type
Right operand : set of
compatible type with left
operand

29/65
When comparison operator are applied to numbers, one of the operand may be of real
type and the other of integer type. The compiler inserts the conversion routine from
integer to real.
Comparison operators applied to string perform comparison with the lexicographic order.
The character type is compatible with the string type. The compiler inserts the conversion
routine from character to single character string.
Two pointers are equal if the value is the same address in memory.
Two sets are equal if they contains the same elements.
If A and B are of set type, A<=B is true if every element of A belongs to B.
The expression x in A returns true if the element x belongs to the set A.
Address operator : The operator @ creates a pointer to a variable. It is a monadic operator
that operates either on a variable reference, on a function identifier or a procedure
identifier. The type of this pointer is the same as nil, with a null domain type, and it is
compatible to all pointer types.
If this operator is applied to a value formal parameter of a procedure or function, the result
is the address in the stack where the parameter has been pushed.
It his operator is applied to a var formal parameter, the result is the address of the variable
which is congruent to this formal parameter in the actual parameter list.
If this operator is applied to a function or a procedure, the value is the address of the
function or procedure in the code segment.

The address operator is not applicable to inline defined procedures or functions.

Function calls. A function call is a function identifier and an optional list of actual
parameters. Each actual parameter must be congruent to the corresponding parameter in
the formal parameter list.
function_call ::= function_identifier [ actual_parameter_list ]
actual_parameter_list ::= ( actual_parameter { , actual_parameter } )
actual_parameter ::= expression | variable_access | procedure_identifier | function_identifier
sum(a,63)
gcd(a,b)
sin(a+b)
first_letter(name)

According to Standard Pascal, and contrary to Turbo Pascal, Pépé implements


procedural parameters.

Set constructor. A set constructor is an expression of set type. It is delimited by brackets [


and ]. It denotes the value of a set.

30/65
set_constructor ::= [ [ member_designator { , member_designator } ] ]

member_designator ::= expression [ .. expression ]

The empty set is denoted by []. Its compatible with all set types.

A member designator x..y denotes the set of all the values in the interval between x and y.
If x is greater than y, it denotes the empty set. All the expressions in all the member
designators of a set constructor must be of the same scalar type.
[green, blue, c]

[1..15]

['a'..'z','A'..'Z','0'..'9','_']

Statements
A statement describes an algorithmic action which is executed. Labels mark statements and
allow jump by a goto statement. These goto are not encouraged by Pascal philosophy.
statement ::= [ label : ] ( simple_statement | structured_statement )
simple_statement ::= empty_statement | assignment_statement | procedure_statement |
goto_statement
Assignment. An assignment statement replace the current value of a variable by a new
value defined by an expression.
assignment_statement ::= ( variable_access | function_identifier ) := expression
An assignment to a function identifier is used to define the return value of a function.
The expression must be assignment compatible with the type of the variable denoted by
the variable access or the return type of the function.
x:=x+y
p := (i>=j) and (i<100)
i:= sqr(j)+i*k

Procedure statement. A procedure statement calls the procedure denoted by the


procedure identifier. If the procedure declaration has a formal parameter list, the procedure
statement must contain an actual parameter list congruent to the formal parameter list.
While the procedure is called, the formal parameters are replaced by the actual parameters.
procedure_statement ::= procedure_identifier [ actual_parameter_list ]
printheader
transpose(a,n,m)
addvectors(s[1],a[2],b[k])

A procedure can also be called through a procedural variable or a procedural


parameter.

31/65
Goto statement. The goto statement branch the program execution to the statement that
just follows the label denoted in the statement.

goto_statement ::= goto label

The label must be in the scope of the goto statement. In particular, it is not possible to
jump into a procedure.

Contrary to many Pascal implementation, it is possible to branch the program


outside a procedure or function. This is convenient to manage error conditions.

program nonlocalgoto;
label 99;
procedure foo(n:integer);
begin
if n<0 then goto 99; // 99 is in the scope of this statement
writeln(n,' is non negative');
end;
begin
foo(-5); // noting will be displayed
99:
end.

Structured statement. Structured statements are blocks of statements, constituted of


more than one statement.
structured_statement ::= compound_statement | conditional_statement | repetitive_statement
| with_statement
A statement sequence delimited by the key words begin and end is seen as a single
statement. A compound statement is required to iterate statements where the Pascal
syntax only allows a single statement.
compound_statement ::= begin statement { ; statement } end
begin
temp:=x;
x:=y;
y:=temp;
end
Conditional statements allows to choose to execute a statement or another depending on
a condition.
conditional_statement ::= if_statement | case_statement
Repetitive statements allows to repeat a same statement under the control of the number
of iteration to execute.
repetitive_statement ::= repeat_statement | while_statement | for_statement
If statement.
if_statement ::= if expression then statement [ else statement ]
The expression, which must be Boolean valued, is evaluated. If the result is true then the
then statement is executed. Otherwise and if it is present, then the optional else statement

32/65
is executed.
if x<1.5 then z:=x+y else z:=1.5

if p1<>nil then p1:=p1^.father


if e1 then if e2 then s1 else s2 // else refers to the second if

Case statement. The case statement consists in an expression, called the selector, together
with a list of statements, prefixed with a constant. If the selector equals one of the
constant, the corresponding statement is executed. The selector and the constants are of
any scalar type. Each constant of the statement list must be unique.
An optional non standard else statement is executed if it is present.
case_statement ::= case selector of case_list_element { ; case_list_element }
[ else_statement ] [ ; ] end
case_list_element ::= case_constant_list : statement
else_statement ::= else statement
case operator of
plus : r:=x+y;
minus : r:=x-y;
times, multiply : r:=x*y;
else goto 666; // error case
end;
Repeat statement.
repeat_statement ::= repeat statement { ; statement } until boolean_expression
The statement sequence is always executed at least once. Then, the Boolean expression is
evaluated and the statement sequences are repeated until this expression is evaluated to
true.
repeat
k:= i mod j;
i:=j;
j:=k;
until j=0;
While statement.
while_statement ::= while boolean_expression do statement
The Boolean expresion that controls the loop is evaluated before executing the loop
statement. If it evaluates to false, then the statement is not executed and the program
continue on the following statement.
If the Boolean expression is evaluated to true, then the statement is executed and the
program returns to the beginning of the while statement.
while info[i]<>x do i:=i+1
while i>0 do
begin
if odd(i) then z:=z*x;
i:= i div 2;

33/65
x:=sqr(x);
end;

For statement. The for statement is repeatedly executed under the control of the value of
a control variable, by comparing the value with a bound before the execution of each
statement loop.
for_statement ::= for control_variable := expression ( to | downto ) expression
do statement
The control variable must be an entire variable, that do not require any qualifier, declared
in the current block. It must be of a scalar type. The initial value and final value expression
are assignment compatible with the type of the control variable.
The final value is evaluated only once at the beginning of the for statement. The value is
memorized in an auxiliary local variable created by the compiler.
The loop statement is executed for each values of the control variable.
If the keyword to is used, then the control variable is incremented by one on each iteration.
If the keyword downto is used, then the control variable is decremented by one on each
iteration.
The loop statement must not modify the value of the control variable. In particular, inside
this statement :
• the control variable cannot be the variable access of an assignment statement,
• a function call with variable parameter cannot invoke the control variable as an
actual parameter,
• the control variable cannot be modified by a read or a readln procedure.
for i:=2 to 63 do if a[1] > max then max:=a[i]
for i:=1 to dim do
for j:=1 to dim do
begin
x:=0;
for k:=1 to dim do
x:=x + mat1[i,k]*mat2[k,j];
mat[i,j]:=x
end
With statement. The with statement creates a temporary environment for references to
fields of a record variable. The record variable do not need to be specified for access to the
fields. An auxiliary variable is created if this record variable is qualified, such that the
evaluation of the qualified record variable is preformed only once at the beginning of the
statement.
with_statement ::= with record_variable { , record_variable } do statement
The statement
with v1, v2, … , vn do s

is equivalent to

34/65
with v1 do
with v2 do
...
with vn do s

The following example :


with date do
if month = 12 then
begin month:=1; year:=year + 1
end
else month:=month+1;
is equivalent to
if date.month = 12 then
begin date.month:=1; date.year:=date.year + 1
end
else date.month:=date.month+1;

Procedures and functions


Procedures and functions define sub blocks of statements in the main section of the
program. Each declaration contains a header and a block.
Procedure declaration. A procedure declaration links an identifier to a statement
sequence
procedure_declaration ::= procedure_header ; directive |
procedure_identification ; block |
procedure_header ; block
procedure_header ::= procedure identifier [ formal_parameter_list ]
procedure_identification ::= procedure identifier
directive ::= forward | inline ( expression { , expression } )
procedure inttostring(n:integer;var s : string);
var v : 0..maxint;
begin
v:=abs(n);
s:='';
repeat
s:=chr((v mod 10) + ord('0')) + s;
v:=v div 10;
until v=0;
if n<0 then s:='-'+s;
end.
A procedure is activated by a procedure statement.
var s : string;
begin
inttostring(-12345,s);
end

The procedure identifier is in the scope of the procedure block. Thus, the procedure block can
contain a procedure statement with its own identifier. In this case, the procedure is called recursive.

35/65
procedure sort(var t : realarray; l,r : integer);
var i,j : integer;
x : real;
begin
i:=l;
j:=r;
x:=t[(l+r)div 2];
repeat
while a[i]<x do i:=i+1;
while x<a[j] do j:=j-1;
if i<=j then
begin
y:=t[i];
t[i]:=t[j];
t[j]:=y;
i:=i+1;
j:=j-1;
end
until i>j;
if l<j then sort(t,l,j);
if i<r then sort(t,i,r);
end;
Function declaration. A function declaration defines a sub program that executes
statements and returns a value.
function_declaration ::= function_header ; directive |
function_identification ; block |
function_header ; block
function_header ::= function identifier [ formal_parameter_list ] : result_type
function_identification ::= function identifier
result_type ::= string | type_identfier
The result value of the function may be a simple type or the string type. It is defined by an
assignment statement invoking the identifier of the function. If this assignment statement
is not present, then the return value of the function is undefined.
function factorial(n:integer):integer;
begin
if n=0 then factorial:=1
else factorial:=n*factorial(n-1);
end;
function reverse(const s:string):string;
var r:string;
l,i : integer;
begin
if s='' then reverse:=''
else
begin
l:=length(s);
for i:=1 to l do r[i]:=s[l-i+1];
r[l+1]:=chr(0); // terminal zero
reverse:=r;
end;
end;

36/65
A function is activated by the evaluation of an expression that contains the call to this
function. The value of the expression is the return value of the function.
begin
writeln(factorial(7)-factorial(6));
end
A function can also be activated in a procedure statement. In this case, the return value is
ignored. This should be used only if the function block has side effect, such as displaying a
result or assigning a result either in a variable parameter or in a global variable.
Forward declaration. A procedure or function declaration with the forward directive
instead of the definition of a block is called a forward declaration. The procedure must be
defined further, by a definition of the block after a procedure or function identification. In a
procedure identification, the formal parameter list is omitted. The formal parameters are
those present in the forward declaration.
The forward declaration and the definition must occur in the same declaration block.
The definition of a forward procedure cannot be inline.
function isodd(n:integer):boolean; forward;
function iseven(n:integer):boolean;
begin
if n=0 then iseven:=true else iseven:=isodd(n-1);
end;
function isodd;
begin
if n=1 then isodd:=true else isodd:=iseven(n-1)
end;
Inline declaration. The inline directive defines a function or a procedure for which the
code is directly inserted in the function or procedure statement while it is invoked.
function times(var t : tms):integer; inline ($e3a07000+43, $ef000000);
function odd(x:integer):boolean; inline($e2000001);
// and r0,r0,#1

Procedure and function statements follows the ARM procedure call standard. The
first parameters are assigned to registers R0 to R4 and the others are pushed on
the stack.
The value of a function is returned in register R0 for scalar values, and in registers
R0 and R1 for real values, with little endian convention.

Parameters. The formal parameter list defines the parameters of a function or procedure.
The parameters declared in this list are local variables, and can be referenced in the
procedure or function block.
formal_parameter_list ::= ( formal_parameter { ; formal_parameter } )
formal_parameter ::= value_parameter_specification | variable_parameter_specification
| constant_parameter_specification
| procedure_header | function_header

37/65
value_parameter_specification ::= identifier_list : type_identifier
variable_parameter_specification ::= var identifier_list [ : type_identifier ]
variable_parameter_specification ::= const identifier_list : type_identifier
Value parameters. A value parameter is a local variable, initialized with the value of the
corresponding expression in the actual parameter list when the function or the procedure
is activated. Modification of a value parameter has no effect outside the procedure or
function.
If the value parameter has type string, the value is copied on the stack and the size is
limited to 255 characters.
Variable parameters. A variable parameter is used when the procedure or the function
need to modify the value of a variable. The corresponding actual parameter in the function
or procedure statement must be a variable.
The actual parameter is the address of this variable, such that each modification of the
variable parameter modifies the value of the variable in the actual parameter list.
procedure increment(var : n integer);
begin
n:=n+1;
end;
If the type is omitted in the formal parameter list, it is a typeless variable parameter, and
any variable of any type is congruent as actual parameter.
Constant parameters. A constant parameter acts as a value parameter, but the value of
the parameter cannot be modified in the block.
A constant parameter is preferable to avoid useless copy of large structure. The actual
value is the address of the actual parameter, and this may lead to more efficient code.
function compare(const s1,s2 : string): boolean;
label 99;
var i, // index variable
l : integer; // length of s1 is computed once
begin
compare:=false; // default value
l:=length(s1);
if l<>length(s2) goto 99;
for i:=1 to l do
if s1[i]<>s2[i] then goto 99;
compare:=true;
99:
end;
For simple types or small structure of size less than 32 bytes, the code generated for value
parameter and for constant parameter is the same.
Procedural parameters. Pépé supports procedural and functional parameters as defined
in Standard Pascal. The actual value of a procedural parameter is the address of the
procedure.

38/65
// apply function f to argument v
function apply(function f(x:real):real; v real):real;
begin
apply:=f(v);
end;
function integrate(function f(x:real):real; a,b: real):real;
begin
// implement your favorite integral calculus algorithm
...
end;
The actual parameter congruent to the procedural formal parameter must be a procedure
or a function with the same header. The variable identifiers in the header of the procedural
parameter are not significant.
writeln(apply(sine,pi));
x:=integrate(cosine,0,pi);

Procedural parameters and variables cannot be assigned with procedures or


functions defined as inline. As most of predefined functions have inline definition,
they cannot be invoked in procedural parameters.

Input / output
A file is a sequence of elements of the same type memorized in the host file system. A file
is associated to a file name. A file can be initialized for reading in inspection mode or for
writing in generation mode.
The predefined reset procedure initializes a file or text in inspection mode, with a given file
name.
reset(f,'file_name');
The predefined rewrite procedure initialize a file or text in generation mode.
rewrite(f,'file_name');
Access to file data in inspection mode and writing data on files in generation mode are
performed through the buffer variable.
The buffer variable is a variable with the same identifier as the file identifier, and of the
same type as the component type of the file. The access to a buffer variable is performed
with the ^ character.
The statement f^:=x assigns the value of x to the variable buffer of file f. This statement
does not write the data on the file. For actually writing the data on the file, the procedure
put(f) must be called.
The statement x:=f^ read the file and assign the element to variable x. On the standard
input, if the buffer variable is empty, it waits that a key is pressed. The procedure get(f)
positions the file to the next position.
The interactive input/output mechanism implemented is supposed to follow the lazy i/o
principle, which means that the procedure get, and all other input procedures, are

39/65
preformed on the latest opportunity.
Similarly the procedure put, and all other output procedures, are performed on the first
opportunity.
Standard input modes. The standard text input has two modes : the buffered mode and
interactive mode. In the buffered mode, a minimal line editor read a line of characters, until
the return key is pressed, and then the characters are read by the program.
In interactive mode, the entered character is read by the program just once it has been
pressed.
The read and readln procedures operates in buffered mode.
If the input buffer is empty, the access to the buffer variable of the standard input text, and
the standard get procedure operates in interactive mode.
If the input buffer is not empty, for example after a read statement, then the input mode
remains in buffered mode until the input buffer is empty.

The standard procedure page is not implemented.

File handling. For convinience, non standard file handling functions are predefined :
• seek(f,n); set the current entry of file f at the n-th position.
• filesize(f); returns the number of entries in the file f.
• filepos(f); returns the current position in the file f.
• erase(name); erases the file named name.

40/65
Predefined types

Boolean
Declaration type boolean = (false,true);

Description Defines the Boolean constants and the result type of relational
operators.

char
Description The character type. It is a 8 bits type denoting characters of the Latin
alphabet. The ordinal value is the ascii code of the character.

integer
Description The integer types. It is implemented by 32 bits signed integer in the
range −231 to 2 31−1

pointer
Description Predefined pointer type with null domain type, compatible with
procedural types and all other typed pointer.

real
Description Floating point number, 64 bits double precision, according to the
IEEE 754 and rounded to the nearest value.

text
Description File of char structured by lines. The two required variables input and
output are of text type.

41/65
Predefined variables and constants

Environ
Declaration var environ : pointer;

Description This variable contains the address of an array of pointers to strings


that define the environment variables.

False
Description Constant defined by the boolean type. The ordinal value is 0.

Input
Declaration var input : text;

Description This is the standard input text (keyboard).

Maxint
Declaration const maxint = 2147483647;

Description This is the maximum value of signed integers ( 2 31−1 )

Output
Declaration var output : text;

Description This is the standard output text (console)

True
Description Constant defined by the boolean type. The ordinal value is 1.

42/65
Predefined functions and procedures

Abs
Description Returns the absolute value of the given numerical parameter.
Comment This function accepts both real and integer parameters, and it
returns a value of the same type.

Arctan
Description Returns the angle in radian whose tangent is given.
Declaration function arctan(x:real):real;

Chr
Description Returns the character that correspond to a given integer value. Only
the 8 less significant bits are taken into account. The others are
ignored.
Declaration Function chr(n:integer):char;

Example Chr(10) returns the newline character, that breaks a string on an


new line.

Close
Description This procedure close an open file or text.
Comment close(f);
The parameter f is any file or text variable.
This procedure has no effect on input and output predefined text
variables.

Clrscr
Description Clears the screen and set the cursor at position (1,1)
Declaration Procedure clrscr;

Comment This procedure is equivalent to rewrite(Output);

Cos
Description Returns the cosine of the given angle in radian.
Declaration function cos(x:real):real;

43/65
dispose
Description This procedure free the memory that has previously been allocated
by a call to the new procedure for the pointer parameter .
Syntax dispose(p)
dispose(p,c1,...cn) See the new procedure.

eof
Description eof(f) returns the end of file indicator of the file f, for any file or text.
Declaration function eof(var f): boolean;

eoln
Description eoln(f) returns the end of line indicator of the text file f.
Comment function eoln(var f:text): boolean;

erase
Description erase(name) erases the file named name.
Declaration procedure erase(const name : string);

Example erase('myfile.txt');

exp
Description Returns e ≈2,71⋯ raise to the power x.
Declaration function exp(x:real):real;

filepos
Description Returns the current position in a file
Déclaration function filepos(var f:file):integer;

Comment The parameter f is compatible with any type of file which is not
text.
The file must be open.

44/65
filesize
Description Returns the number of element in a file
Déclaration function filesize(var f:file):integer;

Comment The parameter f is compatible with any type of file which is not
text.
The file must be open.
The byte size of the file equals the number of elements times the
byte size of the component type of the file.

get
Description get(f) positions the file on the next entry. On the standard input text,
this procedure make the buffer variable empty.
Comment The input file must be in inspection mode.

gotoxy
Description Set cursor position on the screen
Declaration procedure gotoxy(x,y:integer);

Comment The origin is located at (1,1) on the upper left corner of the screen.
If the coordinates are out of the screen bound, they are forced either
to the minimum value, equal to 1, or to the maximum value that
depends on the current screen dimensions.

halt
Description Brusquely leaves the program with a given return value, and returns
to the console.
Declaration procedure halt(output_code:integer);

length
Description Returns the length of a string
Déclaration function length(const s : string): integer;

Comment This function returns the actual number of characters of a string until
the terminal zero.

45/65
ln
Description Returns the natural logarithm in base e
Declaration function ln(x:real):real;

new
Description This procedure create a new variable of dynamic memory.
Syntax new(p) : assign the new created variable to the pointer p. If the
domain type is a record, then the allocated memory size is the
greatest size for all the variants of the record.
new(p,c1,...,cn) : if c1,...,cn are case constant of record type with
variant, the allocated memory size corresponds to the specified
variant.
Example type number_t =
record case integer of
0 : (r : real);
1 : (i : integer);
2 : (s : string);
end;
var p : ^number_t;
...
new(p); // allocates max variant size (256 bytes)
// and assign memory address to p
// such that it may be used for any of
// the variants
new(p,0); // allocates 8 bytes of the real variant
new(p,1); // allocates 4 bytes of the integer variant
There is no run time control that the assigned type is compatible with the
allocated size.

odd
Description This function returns true if the integer parameter is odd, and
false if it is even.
Declaration function odd(x:integer):boolean;

Comment The odd predefined function is implemented inline and cannot be


invoked as a functional parameter or variable.

46/65
ord
Description This function is applicable to any scalar type. It returns the integer
equal to the scalar value.
Comment If n is an integer, then ord(n)returns n
If c is a character, then ord(c) returns the ascii value of c
Ord(false) returns 0
Ord(true) returns 1

pred
Description This function returns the predecessor of the parameter. It takes any
ordinal type and returns a value of the same type.
Comment This function just decrement its parameter. If the parameter is an
enumerated type with assigned values, then the returned value may
not be a valid value.
type enum=(a=1, b=5, c=10);
var x : enum;
begin
x:=pred(b); // the ordinal value assigned to x is 4 !
end;

Example x:=pred(x);

put
Description put(f) writes the current buffer variable f^ on the file (or text) f.
Comment The file or text f must be in generation mode

read
Syntax read([f,] v1[, v2, … , vn] );

Description This procedure load an element of a file in a variable.


The identifier f is any file or text variable. If it is omitted, then it
operates on the input text.
If f is a file variable, each vi is a variable of the same component type
of the file f. On each read of a variable, the file is positioned on the
following element.
read(f,v1,v2,...vn) is equivalent to begin read(r,v1); read(f, v2,...,vn); end
read(f,v) is equivalent to begin v:=f^; get(f); end
If f is a text file, then each vi is a variable of a readable type. The
readable types are integer, real, char and string. The input stream is
read while parsing is possible.

47/65
readln
Description Execute the read procedure on a file text and positions the input text
at the beginning of the next line
Syntax readln [ ( [f,] v1 [, v2, …, vn] ) ];

Comment Readln or readln(f) just position the file at the beginning of the next
line.
When the file is omitted, it operates on the standard input text, and
allows input from the keyboard.

reset
Description Initialize a file or a text for inspection (read mode).
Syntax reset(f [, file_name ] );

Comment If the file name is present, it assigns the name to the file or text.
If the file name is omitted, f must be a text and this procedure reset
the standard output console.
reset(output) just clear the console screen.

rewrite
Description Initialize a file or a text for generation (write mode).
Syntax rewrite (f [ , file_name ] )
Comment If the file name is present, it assigns the name to the file or text.
If the file name is omitted, this procedure only assign the output
console to the specified text.
rewrite(output) has no effect.

round
Description This function returns the nearest integer of a given real parameter.
Declaration function round(x:real):integer;

screenHeight
Description Returns the current height of the screen
Declaration function screenheight:integer;

Comment The value returned by this function may change while the program
runs, depending on the orientation of the device.
The value depends on the screen orientation.

48/65
screenWidth
Description Returns the current width of the screen
Declaration function screenwidth:integer;

Comment The value returned by this function may change while the program
runs, depending on the orientation of the device.
The value depends on the screen orientation.

seek
Description Set the current position of a file at a specified value
Déclaration procedure seek(var f:file, n:integer);

Comment The parameter f is compatible with any type of file which is not
text.
The file must be open.

sin
Description Returns the sine of the given angle in radian.
Declaration function sin(x:real):real;

sizeof
Description Returns a constant integer equal to number of bytes of a variable or
a type.
Comment This function is applicable to any variable and any type identifier.
Example const n = sizeof(integer);

sqr
Description Returns the square of the actual parameter.
Comment This function is applicable to both integer and real type. The
returned value is of the same type as the parameter.
If the parameter is a constant, then the value is precomputed at
compilation time.
Example const n = sqr(sizeof(integer));

sqrt
Description Returns the square root of the parameter.
Declaration function sqrt(x:real):real;

49/65
succ
Description Returns the successor of the parameter. It takes any ordinal type and
returns a value of the same type.
Comment This function just increment its parameter. If the parameter is an
enumerated type with assigned values, then the returned value may
not be a valid value.
type enum=(a=1, b=5, c=10);
var x : enum;
begin
x:=succ(b); // the ordinal value assigned to x is 6 !
end;

trunc
Description This function returns the greatest integer lower than the real
parameter.
Declaration function trunc(x:real):integer;

whereX
Description Returns the x position of the cursor, in the range 1..ScreenWidth
Declaration function wherex:integer;

whereY
Description Returns the y position of the cursor, in the range 1..ScreenHeight
Declaration function wherey:integer;

50/65
write
Description Write expressions on a file.
Syntax write ( [f, ] e1 [ , e2, … , en ] );
Comment The identifier f is any file or text variable. If it is omitted, then it
operates on the standard output, which is the console.
If f is a file variable, each expression ei is of the same component
type of the file f.
write(f, e1,e2,...,en) is equivalent to begin write(f, e1); write(f, e2,...en);
end
write(f,e) is equivalent to begin f^:=e; put(f) end
If f is a text file, then each ei is a writable type expression. The
writable types are integer, real, char, string and boolean. The
expression may be followed by a write parameter with the following
syntax:
write_parameter ::= expression [ : total_width [ : frac_digits ] ]
– expression is the value to be written.
– total_width is an integer valued expression that specifies the
minimal width to be displayed. The display may be completed with
blank spaces
– frac_digits is only significant for displaying real type expression. It
is an integer valued expression that denotes the number of
fractional digits to be displayed.

writeln
Description Executes the write procedure on a text file, and then write an end of
line character.
Syntax writeln [ ( [f, ] e1 [, e2,..., en]) ]
Comment writeln or writeln(f), with no expression, just emits an end of line
character on the specified text file.
When the file is omitted, it operates on the standard output text,
and displays data on the console.

51/65
Les compiler directives
{$i file_name} This directive tells the compiler to include the file file_name in the
compiled text.
{$define name} Defines the symbol name.
{$undef name} If the symbol name was previously defined, this directive undefines it.
{$ifdef name} Starts a conditional compilation. If the symbol name is not defined, this
will skip the compilation of the text that follows it, up to the first {$else} or {$endif}
directive.
If the symbol name is defined, then the compilation continues up to the {$else} directive.
{$else} This directives switches conditional compilation. If the text delimited by the
previous {$if name} directive was ignored, then the text that follows {$else}, up to the
{$endif} directive is normally compiled, and vice versa.
{$endif} This directive ends a conditional compilation sequence.
{$echo message} Displays a message on the console during compilation.

52/65
How to...

Defining some predefined Turbo Pascal functions


Readkey. This function waits and returns a character hit on the keyboard. It may be written
as follows in Standard Pascal :
function readkey:char;
var c : char;
begin
c:=input^;
get(input);
readkey:=c;
end;
Copy. The function copy(s,pos,len) returns the substring form s starting at position pos and
of len characters long. If pos is greater than the length of the string, then it returns the
empty string. Only characters included in the original string are copied, even if len specify a
number of character that is above the length of the string.
function copy(const s : string; pos, len : integer):string;
var r : string; // where the result is build
i,j : integer; // index in source and destination
begin
i:=pos;
j:=1;
if pos<=length(s) then
while (s[i]<>chr(0)) and (j<=len) do
begin
r[j]:=s[i];
i:=i+1;
j:=j+1;
end;
r[j]:=chr(0); // terminal zero
copy:=r;
end;

System calls
System calls can be performed either with ARM assembler defined function, or inline
defined function.
mov r7,#SYSCALL_NUMBER
swi 0

The values of the syscall numbers are in the file “linux-syscall.h” provided in the native
development kit (NDK) of the android system.
Description and declarations of the system functions may be found for example in
http://www.linux.die.net/man/

Example : function times


This system function returns a number of clock ticks from an arbitrary origin and assign
values of the user time, system time, children user time, and children system time.

53/65
The number of ticks per second is 100. This value is given by the macro “#define HZ 100” in
the header file “param.h” of the Android NDK. The syscall number of this function is 43.

a) assembler
Program syscall;

Type tms=record
utime, stime, cutime, cstime : integer;
end;

function times(var t : tms):integer;


asm
mov r7,#43
swi 0
mov pc,lr
end;

begin
writeln(times(nil));
end.

b) as an inline function
Program syscall;

Type tms=record
utime, stime, cutime, cstime : integer;
end;

function times(var t : tms):integer; inline ($e3a07000+43, $ef000000);

begin
writeln(times(nil));
end.

Read the environment variables.


program env; // this program displays the environment strings

type // defining the actual type of the environment variable


pstring =^string; // C-style string = pointer to a string
tpstring = array[0..99] of pstring;
ppstring = ^tpstring;

var
envstrs : ppstring;
x : integer;
begin
envstrs := environ; // the variable 'environ' is predefined
x:=0;
while envstrs^[x]<>nil do
begin
writeln(envstrs^[x]^);
x:=x+1
end;
end.

54/65
Define the Turbo Pascal integer types
type
longint = integer;
word = 0..65535;
byte = 0..255;
shortint = -128..127;
integer = 32768..32768; // take care to redefine integer before

Define 32 bit unsigned integer


type
longword = 0..maxint;

Note that maxint is defined as 2 31−1 but as there is no run time check on the
bounds, this type behaves as 32 bit unsigned integer in the range 0 .. 232−1

55/65
Le Pépé ARM assembler reference
In an assembler defined function or procedure, the comments are the same as in Pascal
section, with {…}, (*...*) or // delimiters.

The processor registers


The ARM processor has 16 general 32 bit registers, r0 to r15. Some of them are dedicated
for special use.
• r0, r1, r2, r3 are used to pass parameters to procedures and functions.
• r0 and r1 are used to return values from functions.
• r4,... r11 are supposed to keep the same value after a procedure call.
• r9 is the base address of shared libraries. It is uses for system calls.
• r10 contains the base address of global variables.
• r11 in the frame register for local variables and parameters
• sp (stack pointer) is a synonym for r13
• lr (link register) is a synonym for r14. It contains the return address of procedures.
• pc (program counter) is a synonym for r15. It contains the address of instructions to
execute.
In addition, the current program status register (CPSR) contains contains the following flags:

31 30 29 28 27 26 ... 8 7 6 5 4 3 2 1 0
N Z C V Q - ... - I F T M4 M3 M2 M1 M0

C carry
Z set if the result is Zero
N set if the result is Negative
is set if an oVerflow has occurred in a signed
V
operation
Q overflow in DSP enhanced instructions
T set while processor runs in THUMB mode
I disable IRQ when set
F disable FIQ when set
M4...M0 defines mode:
• 10000 : User
• 10001 : FIQ
• 10010 : IRQ
• 10011 : Supervisor
• 10111 : Abort
• 11011 : Undefined
• 11111 : System

56/65
Constant definitions
These directives define constant in the code.
• dcb: define byte constant (8 bits). The operand is a list of either integer constant, or
literal strings delimited by simple quotes.
Example:
dcb 'Hello World',0
dcb 1,2,4,4,5,$ff

Each section defined by a dcb directive is word aligned and eventually completed by
zeroes. The strings are not completed by a zero. The terminal zero must be defined
explicitely.
• dch: define half word constant (16 bits).
The operand is a list of 16 bit integer constant.
Example:
dch 1000, 1001, 1002

Each section defined by a dch directive is word aligned and eventually completed
by zeroes.
• dcd: define word constant (32 bits).
The operand is a list of 32 bit integer constants.
Example:
dcd $ffffffff,$73616861
• dcf: define float constant (64 bits IEEE 754 double precision).
The operand is a list of real valued constant. If an integer is specified, then it is
automatically converted into IEEE 754 64 bit double precision format.
Example:
dcf 3.1415, 0.5, 1

Local labels
A label is a sequence of letters, digit and underscore that starts with the @ character, for
example.
@loop_1

It defines the value of destination based on the value of the PC register.


• In branch instructions
@loop
...
bne @loop

• in PC relative data transferts:


ldr r0,@size
...
@size
dcd 5000

57/65
The value of the offset is limited to +/- 4092 bytes for word or unsigned byte data
transfer, and to +/- 252 bytes for signed and half word data transfer. If the offset is
beyond these limits then an error is generated.
• in PC relative address definition:
@my_string
dcb 'Hello world!',0
...
mov r0,@my_string
bl PrintString
The assembler automatically convert this instruction into the suitable
add r0,PC,#offset or sub r0,pc,#offset, depending on the sign of the
offset. Any offset is not implementable in a single instruction. If the value of the
offset cannot be defined in a single instruction, an error is generated.
The scope of a local label is limited to the current assembly bloc.

Condition code.
Each instruction is executed conditionally to the state of the code condition register and
according to a suffix appended to the mnemonic. The remarkable property of the ARM
processor is that this conditional execution is applied to any instruction, not only branch
instructions as usual in most processors.
Suffix Flag Mnemonic
eq Z=1 equal
ne Z=0 not equal
cs C=1 carry set
hs C=1 unsigned higher or same
cc C=0 carry clear
lo C=1 unsigned lower
mi N=1 Minus (negative)
pl N=0 Plus (non negative)
vs V=1 overflow
vc V=1 no overflow
hi C=1 and Z=0 unsigned higher
ls C=0 or Z=1 unsigned lower or same
signed greater than or
ge N=V
equal
lt N<>V signed less than
gt Z=0 and (N=V) signed greater than
le Z=1 or (N<>V) signed less than or equal
al - always

58/65
Example:
function abs(n:integer):integer
asm
cmps r0,#0 // compare r0 with 0
rsbmi r0,r0,#0 // if r0 is negative, then negate it
mov pc,lr // return from subroutine
end;

Branch
• Branch and Exchange This instruction copies the content of a register RDest into the
program counter PC ignoring the least significant bit b0. If this bit equals 1, then, it
switch to THUMB mode, else, it remains in ARM mode. As the program may be
called from THUMB mode, the BX instruction must be used at the end of a program
to return to the OS.
Syntax: ( bx | blx )[cond] RDest
Rdest is the register that contains the destination address.
Bx stands for branch.
Blx stands for branch with link, i.e. the address after this instruction is
loaded into the link register.
Example:
bx r0 // jump to r0 and swicth to mode defined by bit 0
blx r12 // save return address in lr and jump to r12

• Branch This instruction increment the counter program by the signed 24 bit
immediate value contained in the instruction.
• Syntax: B{cond} @label | function identifier | procedure identifier
• Example:
b Error // branch to the procedure Error defined above
@here
...
bne @here // branch to @here if z flag equals 0
b @there // unconditionnal branch to there
...
@there

• Branch with link Same as Branch, but load the link register LR with the content of the
program counter that follows immediately this instruction. This is used for call to
subroutines. The subroutine may be local, if used with a local label, or external, when
used with the identifier of a defined function or procedure.
• Syntax : BL{cond} @label | function identifier | procedure identifier
• Example:
bl @convert // branch to local subroutine convert
...
@convert
blne Pascal_proc // conditional call to an external Pascal
procedure

59/65
Data processing.
The general syntax is
opcode{cond}{s} register{,register},operand
where
operand ::= register{ , shift} | #expr
shiftname
shift ::=
register | shiftname #expression| rrx
shiftname ::= asl | lsl | lsr | asr| ror
expression is either a constant integer valued expression computable at compilation time. It
is coded as a 8 bit value combined with an even rotation. If the value does not fit in this
constraint, then an error is generated.
or a label, only for mov instruction. In this case, the value is the offset relative to the
current position of PC.

opcode can be
and: bitwise logical and dest := op1 and op2
eor: bitwize logical exculsive or. dest := op1 xor op2
sub: arithmetic substraction. dest := op1 - op2
rsb: reversed substraction. dest := op2 - op1
add: arithmetic addition. dest := op1 + op2
adc: addition with carry. dest := op1 + op2 + C
sbc: substraction with carry dest := op1 - op2 + C - 1
rsc: reversed substraction with carry dest := op2 - op1 + C - 1
tst: bit test op1 and op2
teq: equality test op1 eor op2
cmp: comparison op1 - op2
cmn: compare negate op1 + op2
orr: bitwize logical or. dest := op1 or op2
mov: move dest := op2 (op1 ignored)
bic: bit clear dest := op1 and not op2
mvn: move bitwise complement dest := not op2 (op1 ignored)
Shiftname :
lsl: logical shift left
asl: synonym of lsl
lsr: logical shift right
asr: arithmetic shift right, with sign propagation
ror: rotate right
rrx: rotate right one bit with extent, same as ror,#1

60/65
It the indicator s is specified, then the code condition is updated with the result of the
operation.
For test instruction cmp, teq, tst and cmn, the condition code is always set, whatever the
indicator s is specified or not.
Examples.
add r3,r0,r1 // add the content of r0 and r1 and write the result in r3
sbc r0,r0,#0 // negate r0
mov pc,lr // return from subroutine
cmp r0,r2 lsl 2 // compare r0 with 4 times r2
movs r1,r2 lsl r3 // shift right r2 by the amount of r3,
//and write the result in r1 and update the cc register
movne r0,@string // if z=0 then assign the address of @string to r0
// implemented as addne (or subne) r0,pc,#offset

Count leading zeros


This instruction returns in the destination register the number of zero bits before the first
one bit of the source register.
Syntax: clz[cond] Rdest,Rsrc
Rdes is the destination register.
Rsrc is the source register.
Example:
clz r1,r0 // count the number of zero digits of r0
mov r0,r0,lsl r1 // normalize r0 by placing 1 to the most significant bit

Program status register transfert


These instructions copy the program status register.
1. Copy program status register to a register Rn:

Syntax: mrs[cond] Rdest , (cpsr | cpsr_all | spsr | spsr_all)


Rdest is the destination register.
cpsr or cpsr_all (synonyms) :
transfer from the current program status register.
spsr or spsr_all (synonyms):
transfer from the saved program status register (exception mode).
2. Copy program status register from a register Rn

Syntax: msr[cond] (cpsr | cpsr_all | spsr | spsr_all | cpsr_flg | spsr_flg) , Rsrc


Rsrc is the source register.
cpsr or cpsr_all (synonymous)
transfer all bits to the current program status register.
spsr or spsr_all (synonymous)
transfer all bits the saved program status register (exception mode).

61/65
cpsr_flg
transfer only flag bits N, Z, C, V to the current program status register.
spsr_flg
transfer only flag bits N, Z, C, V to the saved program status register
(exception mode).

Multiplication
This instruction multiplies the content of two registers with a result on 32 bits.
Syntax:
mul[cond][s] Rdest,Ra,Rb
mla[cond][s] Rdest,Ra,Rb,Rc
[s]
set condition code if present.
Rdest
is the destination register.
Ra, Rb and Rc
are operands.

mul multiplication Rdest := Ra * Rb


multiplication and
mla Rdest := Ra * Rb +Rc
accumulate

Long multiplication
This instruction multiplies the content of two registers with a result on 64 bits.
Syntax: ( umull | smull | smul |smlal ) [cond][s] Rdest_lo,Rdest_hi,Ra,Rb
[s] set condition code if present.
Rdest_lo and Rdest_hi
are the the destination registers, low and high part respectively.
Ra and Rb are operands.

umull unsigned multiplication (Rdest_lo,Rdest_hi) := Ra * Rb


smull signed multiplication (Rdest_lo,Rdest_hi) := Ra * Rb
multiplication and (Rdest_lo,Rdest_hi) := Ra * Rb +
umlal
accumulate (Rb ,Ra)
signed multiplication and (Rdest_lo,Rdest_hi) := Ra * Rb +
smlal
accumulate (Rb ,Ra)

type
Int64=record // 64 bit integer type
lo,hi : integer;
end;

// 64 bit multiplication a * b --> r

62/65
procedure Mul64(a,b:Int64;var r:Int64);
asm // a=(r0,r1) b=(r2,r3) and address of r is in stack at [r11]
stmfd sp!,(r4,r5) // push them
umull r4,r5,r0,r2 // lo_a * lo_b on 64 bits (r4,r5)
mla r5,r0,r3,r5 // accumulate lo_a * hi_b in r5
mla r5,r1,r2,r5 // accumulate lo_b * hi_a in r5
ldr r12,[r11] // address of r
stmia r12,(r4,r5) // save result there
ldmfd sp!,(r4,r5) // pop them
mov pc,lr // return
end;

Data transfert to and from a register


ldr instruction loads a memory location into a single destination register.
str store the content of a single register into a memory location.
The memory location is defined by an address which is defined by the value of a base
register plus an offset. The offset is either an immediate value contained in the instruction
itself, or the content of an offset register.
The address may be
• pre-indexed: the final address is computed before the transfer.
• post-indexed: the final address is computed after the transfer, the value of the base
register being updated with the final address.
In the pre-indexed mode, the base register may be updated too. This is indicated by a ! in
the instruction.
Syntax:
ldr | str{cond}{b | h | sb | sh}{t} register , address
opcode suffix means
s for sign extension transfer. This is significant for load operation.
b for byte transfer;
h for half word transfer;

address can be
• a local label @label; the final address is an offset from PC.
• a pre-indexed address:
• [ register ] ; the address is given by the value of the register.
• [ register ,# expression ] {!} ; the address is ths sum of the register value and of
the expression.
• [ register , { + | - } register {, shift } ] { ! } ; the address is the sum of the base
register value and of the offset register value eventually shifted.
The ! indicates that the base register is updated with the address value.
• a post-indexed address
• [ register], #expression
• [register], {+|-} register {,shift}
Examples

63/65
@data
dcd 123456
ldr r0,@data // load r0 with 123456

function StrLength(const s:string):integer;


asm
add r2,r0,#1 // memorize starting position
@loop
ldrb r1,[r0],1 // load in r1 byte at address r0 and increment
r0
teqs r1,#0 // test loaded byte
bne @loop // repeat until terminal zero
sub r0,r0,r2 // compute length
mov pc,lr // return from subroutine
end;

Multiple data transfert


These instructions transfer data from/to a memory location defined by a base register
to/from several registers defined by a bitmap in the instruction code.
Syntax:
< ldm | stm >{cond} < fd | sd | fa | ea | ia | ib | da | db > , register { ! }, register_list
the suffixes means:
fd: full descending stack, i.e. post-increment load and pre-decrement store.
ed: empty descending stack, i.e. pre-increment load and post-decrement store.
fa: full ascending stack, i.e. post-decrement load and pre-increment store.
ea: empty ascending stack, i.e. pre-decrement load and post increment store.
ia: increment after.
ib: increment before.
da: decrement after.
db: decrement before.

where register_list is a list of registers delimited by parenthesis (because braces are


comment delimiters in Pascal).
Examples
stmfd sp!,(r0,lr) // push r0 and lr in a full descending stack
...
ldmfd sp!,(r0,pc) // pop r0 and return from subroutine

Data swap
This instrucion swap a word or byte quantity between a register and the memory location
defined by a base register.
Syntax: swp[cond][b] Rdst,Rsrc,'['Rbase']'
[b] if present, it specifies a byte swap, else, it is a word swap.
Rdst is the destination register
Rsrc is the source register
Rbase is the base register

64/65
This instruction write the value of the source register to the memory location and load the
previous content of the memory location in the destination register. These two operation
cannot be interrupted.
swp r1,r2,[r3] // load r1 with the word addressed by r3
// and store r2 at r3

Software interrupt
Syntax: swi[cond] expression
expression is any 24 bit integer value for a comment field ignored by the
processor.
This instruction is used to call the operating system. It branches in supervisor mode to the
interruption vector 8. In general, the expression is interpreted by the interrupt to perform a
given system call.

Breakpoint
Syntax: bkpt expression
expression is any 16 bit integer value for a comment field ignored by the processor
This instruction is always executed. It is used to insert a software break point. It branches in
abort mode to the interruption vector 12.

65/65

You might also like