Почему выравнивание составляет 16 байтов на 64-битной архитектуре? - PullRequest
7 голосов
/ 04 апреля 2011
(gdb) disas foo
Dump of assembler code for function foo:
0x00000000004004a8 <foo+0>: push   %rbp
0x00000000004004a9 <foo+1>: mov    %rsp,%rbp
0x00000000004004ac <foo+4>: mov    0x13c(%rip),%eax        # 0x4005ee <__dso_handle+30>
0x00000000004004b2 <foo+10>:    mov    %eax,-0x10(%rbp)
0x00000000004004b5 <foo+13>:    lea    -0x10(%rbp),%rax
0x00000000004004b9 <foo+17>:    add    $0x18,%rax
0x00000000004004bd <foo+21>:    mov    %rax,%rdx
0x00000000004004c0 <foo+24>:    mov    $0x400498,%eax
0x00000000004004c5 <foo+29>:    mov    %eax,(%rdx)
0x00000000004004c7 <foo+31>:    leaveq 
0x00000000004004c8 <foo+32>:    retq   
(gdb) l foo
8   void foo() {
9       char overme[4] = "WOW";
10      *(int*)(overme+24) = (int)bad;
11  }

Почему не просто 8 байтов?

Ответы [ 2 ]

10 голосов
/ 04 апреля 2011

gcc не «присваивает» это пространство переменной. Скорее abi x86_64 требует, чтобы указатель стека всегда был выровнен по 16 байтов при вызовах функций, в случае, если вызываемый объект использует векторизованную математику SSE. Это действительно глупое и расточительное требование (вызываемый должен обеспечить выравнивание, если это необходимо), но это стандарт, и gcc следует стандарту. Вы можете исправить это с помощью -mpreferred-stack-boundary=3 (8-байтовое выравнивание, минимум для 64-битного).

0 голосов
/ 04 апреля 2011

Это 8 байтов, а не 16. Инструкция LEA не показывает ничего связанного с выравниванием, -0x10 - это просто смещение, примененное к значению регистра RBP.Возможно сформировать адрес небольшого локального массива.Если генератор кода использует какие-либо SIMD-инструкции, то значение 16 может быть релевантным.Ничего из этого не видно в двухстрочном вопросе.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...