.ALIGN
Align the data location counter to a boundary
WSupported on Windows
|
USupported on Unix
|
VSupported on OpenVMS
|
NSupported in Synergy .NET
|
.ALIGN[ boundary]
Arguments
boundary
(optional) One of the following keywords or an expression that specifies the alignment boundary (traditional Synergy only):
BYTE = 1 byte
WORD = 2 bytes
LONG = 4 bytes
QUAD = 8 bytes
PAGE = 512 bytes on Windows and Unix, 4096 bytes on OpenVMS IA64, or 8192 bytes on OpenVMS Alpha
expression = An expression in the range 0 through 9 (n)
Discussion
In Synergy .NET, data is automatically aligned on a native boundary, which causes an automatic align warning to notify of the implicit alignment of objects. The .ALIGN directive suppresses this warning.
In traditional Synergy, the .ALIGN compiler directive aligns the data location counter to a specified boundary for the next data element to be processed. It can help increase an application’s speed by properly aligning integer variables. You can specify .ALIGN before a record or single variable.
We recommend compiling with the -qalign option in traditional Synergy, so you don’t have to use .ALIGN before records. (The -qalign option is always on in Synergy .NET.) |
.ALIGN looks at the address of the next memory location and adds as many filler bytes as necessary to cause the next memory location to fall on the desired boundary. If you specify the BYTE, WORD, LONG, QUAD, or PAGE keyword, the data location counter is aligned to an address that is the next multiple of the number of bytes for that keyword. For example, if the next memory location is 21 and longword alignment is desired, three bytes are added to update the next memory location to 24 (the next higher number that is evenly divisible by 4), thus placing the next variable on a longword-aligned memory boundary.
The default is to align to the natural “int” size on your machine. This is usually longword alignment (4-byte boundaries), except on 64-bit machines, where it is quadword alignment (8-byte boundaries).
If you specify expression, the data location counter is aligned to an address that is the value of 2 raised to the power of expression.
If .ALIGN boundary is used on any system, the alignment is only guaranteed up to the natural register size of that machine. If boundary is larger and memory alignment cannot be guaranteed, a warning (NOTALIGNED) is issued. |
General rules of thumb are as follows:
- i1 variables need not be aligned.
- .ALIGN WORD should precede the first of a sequence of i2 variables.
- .ALIGN LONG should precede the first of a sequence of i4 variables.
- On OpenVMS, .ALIGN without a qualifier (which aligns to a quadword boundary) is recommended.
- For most other RISC processors (IBM RS/6000, MIPS), .ALIGN QUAD should be used, and all integers should be aligned.
If you specify .ALIGN before a declaration that doesn’t define data (such as an overlaid data declaration statement, an EXTERNAL COMMON statement, an EXTERNAL LITERAL statement, or any field in an EXTERNAL COMMON declaration), the compiler generates an “Alignment not performed” warning (NOALIGN).
The .ALIGN directive can cause empty bytes to be allocated between successive data fields. Be careful when redefining the record that contains the .ALIGN directive or when subscripting across an .ALIGN directive, because the empty bytes can be accessed! |
Examples
In the following example, data2 is longword-aligned.
record data1 ,d3 .align LONG data2 ,d8
In the next example, data5 is aligned to a page boundary and data6 through data8 are aligned at the 128-byte boundary with room for future growth.
.align PAGE record data5 ,a90 .align 7 data6 ,a90 .align 7 data7 ,a90 .align 7 data8 ,a90
It’s important to understand the difference between the placement of the .ALIGN statement in these two examples:
record alpha record alpha fld1 ,a1 fld1 ,a1 record beta .align long .align long record beta fld2 ,i4 fld2 ,i4 record gamma, X record gamma, X fld3 ,i4 fld3 ,i4
The example on the left causes fld2 to be aligned on a longword boundary and allows fld2 to be accessed as efficiently as possible. The problem with this approach is not always apparent. The .ALIGN LONG has increased the size of record beta, and fld3 no longer overlays fld2 properly. You would see this easily if ^SIZE(beta) were displayed. In this case, the size of record beta is 7, and only the fourth byte of fld3 coincides with fld2, which is not the desired effect.
When the .ALIGN LONG is moved before the record, as in the example on the right, the size of record beta is 4 as desired. But what about the size of record alpha? In the left example, the size of record alpha is quite obviously 1. If we displayed ^SIZE(alpha) in this example, we’d see it’s still 1. So now we wonder, is fld2 really aligned as desired, and where are the 3 bytes needed for alignment? The answer is that fld2 is aligned, and the extra 3 bytes have been added to the data division between the two records and not as part of either record. ^SIZE(alpha) is 1, ^SIZE(beta) is 4, ^SIZE(gamma) is 4, and fld3 and fld2 coincide as desired.