# Ada Programming/Attributes/'Bit Order
## Description

R'Bit_Order is a representation attribute used to specify the bit numbering of a record representation clause (for a record type). The bit ordering is of type System.Bit_Order, and may be either:
* High_Order_First when the bit 0 is the most significant bit
* Low_Order_First when the bit 0 is the least significant bit
assuming the bit sequence is interpreted as an integer value. The constant System.Default_Bit_Order represents the native bit numbering of the platform.
It is worth noting that the bit ordering only affects the bit numbering for a record representation clause, and not the byte order of its (multibyte) fields.

## Introduction

Storage units are ordered by their addresses. Let's look at an integer occupying several bytes (let's assume a byte being 8 bits for this discussion).
* On a big endian (BE) machine, the integer's most significant byte is stored at the least address.
* On a little endian (LE) machine, its least significant byte is stored at the least address.
So in order to be able to count bits consecutively across byte boundaries, Ada counts bits within a byte according to the endianness from most significant bit (MSB) 0 to least significant bit (LSB) on BE and the other way round on LE.
This is how it looks (conveniently writing left to right on BE, right to left on LE):
We're used to writing left to right, but for LE, as you can see, it's convenient to write addresses from right to left. So on BE, a sequence of bytes and bits is counted like this:
In order to be able to write and count consecutively on LE, we have to write right to left like for example in the Arabian or Hebrew scripts (the MSB is always on the left; this seems to be a global trait in all modern scripts):
In a record representation like the following (of course only one of the two lines specifying X may be present)
the component X occupies the bits shown in boldface. The byte number (0 resp. is 1) is called Position, the bounds are called First_Bit (13 resp. 5) and Last_Bit (17 resp. 9); there are corresponding attributes 'Position, 'First_Bit and 'Last_Bit. (The meaning of the component X is irrelevant here, only its size is relevant.) As you can see, X is a crossborder component. Thus the result of applying the attribute 'Bit_Order to a record with crossborder components depends on the Ada generation.

## Ada 95

Ada 95 defines the result of the attribute for the non-native bit order only when applied within a storage unit or when an item completely fills a sequence of storage units. By applying the attribute to a record, we force the compiler to count bits in the indicated manner, independent of the machine architecture.
The component B occupies the bits shown in boldface:
The layout of this record will be the same on BE and on LE machines, i.e. the representation is endian-independent.
We could equally well have defined this record like so and arrived at the same endian-independent layout:
However a record like the following, where B is crossborder, is only valid on a BE machine, i.e. in the native bit order.
Compiled on a LE machine, the compiler will complain that B occupies non-contiguous storage and reject the code, since the byte order is not affected by the attribute (remember, the next byte with bit numbers 8 to 15 has to be put on the left):
As an example of a record where items fill a range of complete storage units take:
This is valid on both architectures leading to the layout:
where A fills the bits in normal face, B those in bold face. As you can see, it doesn't matter that bits are counted in this strange way on LE since component B fills its two bytes completely.

## Ada 2005

For the native bit order, there is no change. Record representation specifications have worked since Ada 83. Only the attribute 'Bit_Order has been introduced in Ada 95 with the restrictions as shown above.
In order to improve the situation for non-native bit orders, Ada 2005 introduces the notion of machine scalars. A machine scalar is a conceptual hardware based unsigned integer within which bits are counted and the components positioned as requested.
We need a more elaborated record example now (the values returned by the corresponding attributes 'Position, 'First_ and 'Last_Bit (in native bit order) are given as comments; note that the bit numbers returned are always counted starting with the byte in which the component begins):
Let's assume I is a 16 bit (signed or unsigned) integer, the other components are of some unspecified types with the given size requirements. The complete record's size is 48. This is how it looks like on BE and LE machines:
In the following, we're going to show how far we can go to reach endian-independence of the representation. The result will be that we only have to swap bytes after transfer from one architecture to the other when the new Ada 2005 features are used correctly.
For the following, we'll assume that we are on a big-endian machine, so that we append the corresponding attribute to the representation:
When this is compiled on a little-endian machine, all components with the same Position are taken together and put in a matching machine scalar. The machine scalar is positioned at the given Position, but inside the bits are counted from the opposite side.
Let's take the first component, I. It uses 16 bits, so a 16 bit machine scalar will do. It is positioned at byte 0, but inside the compiler will count from the high order bit side. This is how it looks (NNBO - non-native bit order):
Now to the next Position 2. The respective components A, B, C use together three bytes, so a 32 bit machine scalar is needed. It is positioned at byte 2, and inside the count will again start from the opposite side. This is how it looks:
The bit count starts at the high order bit of byte 5 and continues down to the low order bit of byte 2. The components A, B, C are positioned inside this scalar according to the respective ranges. Thus we arrive at this layout:
We immediately see the conflict with component D, whose range is already occupied by A, and the compiler will of course complain and reject the code. The solution is simple: Just instead of locating D at Position 5, we change this to the (on BE) equivalent line like so:
And, drum roll, on LE, we now have (for comparison, the native layout is also given):
In the non-native bit order, the values returned by the corresponding attributes 'Position, 'First_ and 'Last_Bit are exactly those given in the record specification.
As an additional service, GNAT's compilation output will give you the values as counted in the native bit order within the machine scalar:
This is as far as we can get with the current Ada standard.

## Data Transfer

Let us transfer a value of this record from the native big-endian machine to a little-endian machine. For demonstration purposes, the high-order parts of the crossborder items are shown in upper case, the low-order parts in lower case.
The bytes will be transferred in the given order. Since the bit order attribute does not reorder the bytes after transfer, on the target machine we will receive the data in scrambled order:
All we have to do to arrive at the desired end, is to swap bytes 0↔1, 2↔5, 3↔4:

## Example

The following two sets of representation clauses specify the same register layout in any machine / compiler (Ada 2005 and later):
If the bit order is modified, the bit numbering of all the elements of the record representation clause must be reversed:
Both can be interchangeably used in the same machine. But note that in two machines with different endianness the Data field will have the native byte order regardless of the bit order specified in the representation clauses.

## Incorrect Usage

The 'Bit_Order attribute is not intended to convert data between a big-endian and a little-endian machine (it affects bit numbering, not byte order). The compiler will not generate code to reorder multi-byte fields when a non-native bit order is specified.

## References

* ↑ Note that when the ARM talks about "big endian" and "little endian" in the definition of the 'Bit_Order attribute it really means bit endianness, not byte endianness. (Nowadays the term endianness is usually reserved for talking about byte order, although it can also be used for bit numbering.) Thus, in this context, when the ARM says "little endian" it refers to "LSB 0", and when it says "big endian" this is the same as "MSB 0": «High_Order_First (known in the vernacular as “big endian”) means that the first bit of a storage element (bit 0) is the most significant bit (interpreting the sequence of bits that represent a component as an unsigned integer value). Low_Order_First (known in the vernacular as “little endian”) means the opposite: the first bit is the least significant.»
* ↑ ISO/IEC 8652:1987. "13.4 Record Representation Clauses". Ada 83 Reference Manual. The range defines the bit positions of the storage place, relative to the storage unit. The first storage unit of a record is numbered zero. The first bit of a storage unit is numbered zero. The ordering of bits in a storage unit is machine_dependent and may extend to adjacent storage units. {{cite book}}: Unknown parameter |chapterurl= ignored (|chapter-url= suggested) (help)
* ↑ AI95-00133-01 (1996-05-07). "Controlling bit ordering". Class: binding interpretation. Ada Rapporteur Group. Bit_Order clauses are concerned with the numbering of bits and not concerned with data flipping interoperability.
* ↑ ISO/IEC 8652:2007. "13.5.3 Bit Ordering (9/2)". Ada 2005 Reference Manual. Retrieved 2008-06-02. Bit_Order clauses make it possible to write record_representation_clauses that can be ported between machines having different bit ordering. They do not guarantee transparent exchange of data between such machines. {{cite book}}: Unknown parameter |chapterurl= ignored (|chapter-url= suggested) (help)
* ↑ Thomas Quinot (2013). "Gem #140: Bridging the Endianness Gap". AdaCore. Retrieved 2013-01-31. the order in which the bytes that constitute machine scalars are written to memory is not changed by the Bit_Order attribute -- only the indices of bits within machine scalars are changed. {{cite web}}: Unknown parameter |month= ignored (help)

## Interfacing

Record representation clauses are a unique feature of the Ada language as far as the authors know, so there is no need to have a feature similar to attribute 'Bit_Order in other programming languages. It is common practice in other programming languages to use masks and bit operations explicitly, thus the native bit numbering must always be used.

## See also
### Wikibook

* Ada Programming
* Ada Programming/Attributes
* Ada Programming/Attributes/'Position
* 'First_Bit
* 'Last_Bit

### Ada Reference Manual

* 13.5.3 Bit Ordering (Annotated)
* Annex K Language-Defined Attributes (Annotated)

### Ada Rationale

* Ada 95: 13.1 Representation of Data
* Ada 2005: 9.2.1 Incompatibilities with original Ada 95

## Further reading

* Norman H. Cohen (1994). "Endian-independent record representation clauses" (PDF). ACM SIGAda Ada Letters. New York, NY, USA: Association for Computing Machinery. XIV (1): 27–29. ISSN 1094-3641. Retrieved 2008-12-20.
* Randal P. Andress (2005). "Wholesale byte reversal of the outermost Ada record object to achieve endian independence for communicated data types" (PDF). ACM SIGAda Ada Letters. New York, NY, USA: Association for Computing Machinery. XXV (3): 19–27. ISSN 1094-3641. Retrieved 2008-12-20.