This section is about memory accesses useful for communicating with other software or other computers. This means that the accesses are of a certain bit width (independent of Gforth’s cell width), are possibly not naturally aligned and typically have a certain byte order that may be different from the native byte order of the system that Gforth runs on.
We use the following prefixes:
c
8 bits (character)
w
16 bits
l
32 bits
x
64 bits represented as one cell
xd
64 bits represented as two cells
The x
-prefix words do not work properly on 32-bit systems, so
for code that is intended to be portable to 32-bit systems you should
use xd
-prefix words. Note that xd
-prefix words work on
64-bit systems: there the upper cell is just 0 (for unsigned values)
or a sign extension of the lower cell.
The memory-access words below all work with arbitrarily (un)aligned
addresses (unlike @
, !
, f@
, f!
, which
require alignment on some hardware).
w@
( c-addr – u ) gforth-0.5 “w-fetch”
u is the zero-extended 16-bit value stored at c_addr.
w!
( w c-addr – ) gforth-0.7 “w-store”
Store the bottom 16 bits of w at c_addr.
l@
( c-addr – u ) gforth-0.7 “l-fetch”
u is the zero-extended 32-bit value stored at c_addr.
l!
( w c-addr – ) gforth-0.7 “l-store”
Store the bottom 32 bits of w at c_addr.
x@
( c-addr – u ) gforth-1.0 “x-fetch”
u is the zero-extended 64-bit value stored at c_addr.
x!
( w c-addr – ) gforth-1.0 “x-store”
Store the bottom 64 bits of w at c_addr.
xd@
( c-addr – ud ) gforth-1.0 “x-d-fetch”
ud is the zero-extended 64-bit value stored at c_addr.
xd!
( ud c-addr – ) gforth-1.0 “x-d-store”
Store the bottom 64 bits of ud at c_addr.
For accesses with a specific byte order, you have to perform byte-order adjustment immediately after a fetch (before the sign-extension), or immediately before the store. The results of these byte-order adjustment words are always zero-extended.
wbe
( u1 – u2 ) gforth-1.0 “wbe”
Convert 16-bit value in u1 from native byte order to big-endian or from big-endian to native byte order (the same operation)
wle
( u1 – u2 ) gforth-1.0 “wle”
Convert 16-bit value in u1 from native byte order to little-endian or from little-endian to native byte order (the same operation)
lbe
( u1 – u2 ) gforth-1.0 “lbe”
Convert 32-bit value in u1 from native byte order to big-endian or from big-endian to native byte order (the same operation)
lle
( u1 – u2 ) gforth-1.0 “lle”
Convert 32-bit value in u1 from native byte order to little-endian or from little-endian to native byte order (the same operation)
xbe
( u1 – u2 ) gforth-1.0 “xbe”
Convert 64-bit value in u1 from native byte order to big-endian or from big-endian to native byte order (the same operation)
xle
( u1 – u2 ) gforth-1.0 “xle”
Convert 64-bit value in u1 from native byte order to little-endian or from little-endian to native byte order (the same operation)
xdbe
( ud1 – ud2 ) gforth-1.0 “xdbe”
Convert 64-bit value in ud1 from native byte order to big-endian or from big-endian to native byte order (the same operation)
xdle
( ud1 – ud2 ) gforth-1.0 “xdle”
Convert 64-bit value in ud1 from native byte order to little-endian or from little-endian to native byte order (the same operation)
For signed fetches with a specific byte order, you have first have to perform an unsigned fetch and a byte-order correction, and finally use a sign-extension word:
c>s
( x – n ) gforth-1.0 “c-to-s”
Sign-extend the 8-bit value in x to cell n.
w>s
( x – n ) gforth-1.0 “w-to-s”
Sign-extend the 16-bit value in x to cell n.
l>s
( x – n ) gforth-1.0 “l-to-s”
Sign-extend the 32-bit value in x to cell n.
x>s
( x – n ) gforth-1.0 “x>s”
Sign-extend the 64-bit value in x to cell n.
xd>s
( xd – d ) gforth-1.0 “xd>s”
Sign-extend the 64-bit value in xd to double-cell d.
Overall, this leads to sequences like
w@ wbe w>s \ 16-bit unaligned signed big-endian fetch >r lle r> l! \ 32-bit unaligned little-endian store