Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What does .p2align do in asm code?

Tags:

gcc

assembly

I have this assembly directive called .p2align that is being generated by gcc from the source of a C program.

As I understand aligned access is faster that the unaligned one, also an asm program doesn't automatically align the memory locations or optimize memory access, so you have to do this.

I can't really read this .p2align 4,,15, especially the last part, that 15.

Skipping the fact that apparently gcc generates 2 , instead of just 1, as reported by many docs; what I get is that this piece of asm aligns memory in such a way that each location occupies 2^4 bits, which means 16 bit, so I think that it's fair to say that a WORD is 16 bit long in this case.

Now what 15 possibly means ? It's a number of bits for what ? Does the counting start from 0 so the "real" quantity is 16 instead of 15 ?

EDIT:

I just translated the same C source to both 32 bit and 64 asm code, the memory is always aligned in the same exact way with the same directive .p2align 4,,15. Why is that ?

like image 393
user2485710 Avatar asked Feb 04 '14 08:02

user2485710


2 Answers

The .p2align directive is documented here.

The first expression is the power-of-two byte alignment required. .p2align 4 pads to align on a 16-byte boundary. .p2align 5 - a 32-byte boundary, etc.

The second expression is the value to be used as padding. For x86, it's best to leave this and let the assembler choose, since there are a range of instructions that are effective no-ops. In some alignment directives, you'll see 0x90, which is the NOP instruction.

The final expression is the maximum number of bytes for padding - if the alignment requires more than this, skip the directive. In this case - 4,,15 - it does nothing, since 15 is the maximum number of bytes required to yield 16-byte alignment anyway.

like image 119
Brett Hale Avatar answered Nov 17 '22 02:11

Brett Hale


The p2 part of the directive name came from gas being possibly the original implementation of the recommendation for Intel P-II CPU to provide conditional alignment of loop body code. As Agner Fog explains, the original purpose was to ensure that the first instruction fetch gets sufficient code to begin decoding.

There is also an interaction with the Loop Stream Detector, which may fail to kick in if there are extra instruction cache line fragments used at the top and bottom of the loop. Alignment is made conditional so as to avoid consuming more memory than necessary, and to avoid excessive time requirement in the case where the padding bytes are executed. gcc makes different choices of alignment, depending on the mtune target setting.

There have been targets where 2 alignment directives are set, for example to make unconditional 8-byte alignment and conditional 32-byte alignment. The reason for choosing various nop patterns is to minimize the time taken in the case where the padding stream is executed (when execution enters the loop from above). For example, a prefixed instruction which copies a register to itself can consume code bytes faster than single byte nops. This makes no difference in the case originally alluded to in this thread. So, part of the confusion may come from this alignment directive having features which aren't relevant to setting data alignments, although the directive is used also for that purpose.

like image 43
tim18 Avatar answered Nov 17 '22 03:11

tim18