Звучит не для конкретного стека, а для выравнивания в целом.Возможно, придумайте термин целое число, кратное.
Если в памяти есть элементы размером в байт, единицы 1, то давайте просто скажем, что все они выровнены.Вещи размером два байта, затем целые числа 2 будут выровнены, 0, 2, 4, 6, 8 и т. Д. И нецелые кратные 1, 3, 5, 7 не будут выровнены.Элементы размером 4 байта, целые кратные 0, 4, 8, 12 и т. Д. Выровнены, 1,2,3,5,6,7 и т. Д. - нет.То же самое касается 8, 0,8,16,24 и 16 16,32,48,64 и так далее.
Это означает, что вы можете посмотреть на базовый адрес элемента и определить, выровнен ли он.
size in bytes, address in the form of
1, xxxxxxx
2, xxxxxx0
4, xxxxx00
8, xxxx000
16,xxx0000
32,xx00000
64,x000000
and so on
В случае компиляции данных с инструкциями в инструкциях.Для текстового сегмента достаточно просто выровнять данные по мере необходимости (ну, это зависит от архитектуры).Но стек - это вещь времени выполнения, компилятор не может нормально определить, где будет находиться стек во время выполнения.Поэтому во время выполнения, если у вас есть локальные переменные, которые необходимо выровнять, вам нужно, чтобы код корректировал стек программно.
Скажем, например, у вас есть два 8-байтовых элемента в стеке, всего 16 байт, и вы действительно хотите, чтобы они были выровнены (на 8-байтовых границах).При входе функция вычитает 16 из указателя стека, как обычно, чтобы освободить место для этих двух элементов.Но чтобы выровнять их, нужно было бы больше кода.Если мы хотим, чтобы эти два 8-байтовых элемента были выровнены по 8-байтовым границам, а указатель стека после вычитания 16 был 0xFF82, то младшие 3 бита не равны 0, поэтому он не выровнен.Три младших бита - 0b010.В общем смысле мы хотим вычесть 2 из 0xFF82, чтобы получить 0xFF80.То, как мы определяем, что это 2, будет зависеть от 0b111 (0x7) и вычитать эту сумму.Это означает, что все операции a и и вычитают.Но мы можем сократить путь, если мы и со значением 0x7, равным 0x7 (~ 0x7 = 0xFFFF ... FFF8), получим 0xFF80, используя одну операцию alu (при условии, что компилятор и процессор имеют для этого один код операции,в противном случае это может стоить вам больше, чем и вычитать).
Похоже, именно это и делает ваша программа.Оболочка с -16 - это то же самое, что и над 0xFFFF .... FFF0, в результате чего адрес выровнен по 16-байтовой границе.
Так что оберните это, если у вас есть что-то вроде типичного стекауказатель, который перемещается вниз по памяти от старших адресов к младшим, затем вы хотите
sp = sp & (~(n-1))
, где n - количество байтов для выравнивания (должно быть степенями, но это нормально, большинство выравниваний обычно включает полномочиядва).Если вы сказали, что сделали malloc (адреса увеличиваются от низкого к высокому) и хотите выровнять адрес чего-либо (не забывайте malloc больше, чем вам нужно, по крайней мере, на размер выравнивания), тогда
if(ptr&(~(n-)) { ptr = (ptr+n)&(~(n-1)); }
Или есливам нужно просто взять if и выполнять добавление и маску каждый раз.
У многих / большинства архитектур, отличных от x86, есть правила и требования выравнивания.x86 слишком гибок в том, что касается набора инструкций, но за выполнение вы можете / будете платить штраф за невыровненный доступ к x86, поэтому даже если вы можете это сделать, вы должны стремиться оставаться выровненными, как если быдругая архитектура.Возможно, именно это и делал этот код.