# Accessing memory

## Alignment discipline

Some platforms that Dusk OS runs on (ARM) have restrictions with regards to
unaligned memory access: 16-bit memory access have to be done on even addresses
and 32-bit ones have to be done on addresses divisible by 4.

This imposes what we call an "alignment discipline" on all of Dusk OS' code.

The biggest unalignment source is already handled by the kernel: all new
dictionary entries are always created aligned. Therefore, whenever you use
"create" or "value" or other such words, you don't have to worry about whether
you're aligned.

However, in some cases, you do have to worry about alignment as an operator:
"here" is not always aligned! For example, starting from an aligned "here",
this code:

  ," foo"

results in "here" becoming unaligned because 3 bytes were written.

This type of situations mostly arises in structs' [doc/usage/ns] ":new" methods,
but can arise in other contexts too.

Therefore, the general rule is that when you're about to access memory related
to here in 16-bit or 32-bit mode, you need to align "here". You can do so with
the "align4" word, but there's also the shortcut "here#" which aligns "here" and
then yield it.

Therefore, the general rule of thumb is: use "here#" instead of "here".

For structs, (which includes C structs), you have to arrange your fields
accordingly. By principle, no auto-alignment takes place on structures. The idea
is that looking at a structure's definition should always tell the reader the
exact structure without them having to second guess.

To help, there are alignment checks built in. When a structure's definition
results in misaligned fields, Dusk aborts with "alignment error".

## Range words and alignment optimization

Range words [doc/usage/lit] that are binary modulable [doc/usage/bwm] need of
course to be called with addresses that are properly aligned. Doing something
like "$123 $456 42 move" will result in a crash on systems that can't do
unaligned memory accesses.

However, processing ranges in 4 bytes chunks is faster than doing so in 1 byte
chunks. In cases where we're not sure whether the addresses we have is aligned,
do we have an easy option for doing the "right thing"? Yes.

Many binary modulable range words have a "c" variant, which is a functional
shortcut to their 8b variant. For example, "cfill" is the same as "8b fill".

Although they're functionally equivalent, they sometimes don't have the same
implementation. When possible, the "c" variants will do alignment optimization.
For example, if you call "cmove ( src dst u -- )" with aligned arguments, then
what will be done will be to call the 32-bit "move" with "u/4". "8b move" will
always do the "dumb" thing.

Some of those words such as "cfill" and "cidx" can't do this because doing so
wouldn't be functionally equivalent to the 8b version. So they don't.

## Endian-ness

In Dusk, memory accesses are done in the CPU's native endian-ness.

However, we also have words to read 32-bit or 16-bit values in arbitrary
endian-ness regardless of host's endian-ness.

Two endian-ness are supported, little-endian (LE) and big endian (BE). Let's
consider this memory arrangement:

A+0  A+1  A+2  A+3
$12  $34  $56  $78

This memory can be read as little endian, that is, the least significant byte
first, with "le@ ( a -- n ). It reads as $78563412. It can also read as big
endian, that is, the most significant byte first, with "be@ ( a -- n )". It then
reads as $12345678. Same principle for writing.

Each of these words have a 16-bit variant, so they can be called with a "16b"
modulator. They don't have a "8b" one because it makes no sense.

On top of that, there's "fieldle" and "fieldbe" [doc/usage/bind] which are
endian-ness aware versions of "field". Those words support only "to" and "to'".

Additionally, these words can ignore alignment discipline because they are
guaranteed to read and write byte by byte.

The tradeoff is that these words are slower than their native counterpart.
