Address arithmetic is the foundation on which you can build data structures like arrays, records (see Structures) and objects (see Object-oriented Forth).
Standard Forth does not specify the sizes of the data types. Instead,
it offers a number of words (e.g., cells
) for computing sizes
and doing address arithmetic.
Address arithmetic is performed in terms of address units (aus); on
most systems the address unit is one byte. There is also
word-addressed12
hardware in some embedded systems, and on these systems the au is one
cell. Finally, Forth-2012 also supports systems where a char needs
more than one au. However, the common practice is that 1 chars
produces 1, and this will be standardized in the next release of the
standard.
The basic address arithmetic words are +
and -
. E.g., if
you have the address of a cell, perform 1 cells +
, and you will
have the address of the next cell.
Standard Forth also defines words for aligning addresses for specific types. Some hardware requires that accesses to specific data types must only occur at specific addresses; e.g., that (4-byte) cells may only be accessed at addresses divisible by 4. Even if a machine allows unaligned accesses, it can usually perform aligned accesses faster.
For the performance-conscious: alignment operations are usually only necessary during the definition of a data structure, not during the (more frequent) accesses to it.
Standard Forth defines no words for character-aligning addresses, but
given that 1 chars
=1 is common practice, that’s not a big loss.
Standard Forth guarantees that addresses returned by CREATE
d words
are cell-aligned; in addition, Gforth guarantees that these addresses
are aligned for all purposes.
Note that the Standard Forth word char
has nothing to do with address
arithmetic.
chars
( n1 – n2 ) core “chars”
n2 is the number of address units of n1 chars.
char+
( c-addr1 – c-addr2 ) core “char-plus”
1 chars +
.
char-
( c-addr1 – c-addr2 ) gforth-0.7 “char-minus”
cells
( n1 – n2 ) core “cells”
n2 is the number of address units of n1 cells.
cell+
( a-addr1 – a-addr2 ) core “cell-plus”
1 cells +
cell-
( a-addr1 – a-addr2 ) core “cell-minus”
1 cells -
cell/
( n1 – n2 ) gforth-1.0 “cell-divide”
N2 is the number of cells that fit into n1 aus, rounded towards negative infinity.
cell
( – u ) gforth-0.2 “cell”
Constant
– 1 cells
aligned
( c-addr – a-addr ) core “aligned”
a-addr is the smallest aligned address greater than or equal to c-addr.
floats
( n1 – n2 ) floating “floats”
n2 is the number of address units of n1 floats.
float+
( f-addr1 – f-addr2 ) floating “float-plus”
1 floats +
.
float
( – u ) gforth-0.3 “float”
Constant
– the number of address units corresponding to a floating-point number.
float/
( n1 – n2 ) gforth-1.0 “float-divide”
N2 is the number of floats that fit into n1 aus, rounded towards negative infinity.
faligned
( c-addr – f-addr ) floating “f-aligned”
f-addr is the first float-aligned address greater than or equal to c-addr.
sfloats
( n1 – n2 ) floating-ext “s-floats”
n2 is the number of address units of n1 single-precision IEEE floating-point numbers.
sfloat+
( sf-addr1 – sf-addr2 ) floating-ext “s-float-plus”
1 sfloats +
.
sfloat/
( n1 – n2 ) gforth-1.0 “s-float-divide”
N2 is the number of sfloats that fit into n1 aus, rounded towards negative infinity.
sfaligned
( c-addr – sf-addr ) floating-ext “s-f-aligned”
sf-addr is the first single-float-aligned address greater than or equal to c-addr.
dfloats
( n1 – n2 ) floating-ext “d-floats”
n2 is the number of address units of n1 double-precision IEEE floating-point numbers.
dfloat+
( df-addr1 – df-addr2 ) floating-ext “d-float-plus”
1 dfloats +
.
dfloat/
( n1 – n2 ) gforth-1.0 “d-float-divide”
N2 is the number of dfloats that fit into n1 aus, rounded towards negative infinity.
dfaligned
( c-addr – df-addr ) floating-ext “d-f-aligned”
df-addr is the first double-float-aligned address greater than or equal to c-addr.
maxaligned
( addr1 – addr2 ) gforth-0.2 “maxaligned”
addr2 is the first address after addr1 that satisfies all alignment restrictions.
*aligned
( addr1 n – addr2 ) gforth-1.0 “star-aligned”
addr2 is the aligned version of addr1 with respect to the alignment n.
*align
( n – ) gforth-1.0 “star-align”
Align here
with respect to the alignment n.
waligned
( addr – addr’ ) gforth-1.0 “waligned”
Addr’ is the next even address >= addr.
walign
( – ) gforth-1.0 “walign”
Align here
to even.
laligned
( addr – addr’ ) gforth-1.0 “laligned”
Addr’ is the next address >= addr divisible by 4.
lalign
( – ) gforth-1.0 “lalign”
Align here
to be divisible by 4.
xaligned
( addr – addr’ ) gforth-1.0 “xaligned”
Addr’ is the next address >= addr divisible by 8.
xalign
( – ) gforth-1.0 “xalign”
Align here
to be divisible by 8.
The environmental query address-unit-bits
(see Environmental Queries) and the following words may be useful to those who want to
write software portable to non-byte-addressed machines.
/w
( – u ) gforth-0.7 “slash-w”
address units for a 16-bit value
/l
( – u ) gforth-0.7 “slash-l”
address units for a 32-bit value
/x
( – u ) gforth-1.0 “slash-x”
address units for a 64-bit value