Я спрашиваю о соответствии требованиям ABI x64.Безопасно ли настраивать стек вслепую, увеличивая его на 8 байт для 16-байтового выравнивания после каждого вызова.
Да, в этом весь смысл ABI, требующий / гарантирующий 16-байтовое выравнивание до a call
.
Вы можете делать что угодно внутри функции, например, 3x 16-битные нажатия и затем sub rsp, (24 - 3*2)
для восстановления 16-байтное выравнивание стека после входа в функцию.
или movq xmm0, rsp
, а затем используйте rsp
в качестве дополнительного регистра с нулями, чтобы получить 16 полных целочисленных регистров, пока вы не восстановите его перед выполнением другого call
или ret
. 1
Не требуется, чтобы RSP выравнивался по 16 байтов после каждой инструкции , только на границах вызова функции. Этопочему они называются «соглашениями о вызовах», а не «стандартами кодирования».
Это похоже на концепцию rbx, сохраняющую вызов.Не имеет значения, сохраните ли вы его / восстановите в стеке, в xmm0, в статическом хранилище, если вы отрицаете его, а затем снова отрицаете, или если вы вообще не трогаете его.Все, что имеет значение, это то, что оно имеет то же значение при возврате к вызывающей стороне, что и при вызове вашей функции.
Сноска 1: Работает, пока у вас нет асинхронных обратных вызовов /Обработчики SEH, которые могут работать в стеке пользовательского пространства.На самом деле это не гарантированно безопасно, но может работать как хак.
Допустимо ли писать ниже ESP? имеет отношение: как указывает Ped7g, если что-то может асинхронно использовать пространствониже указателя стека, он, вероятно, сломается, если RSP вообще не будет указывать на память стека.
Я видел 32-битный пример видеофильтра avisynth (я думаю), который использовал это, чтобы получить 8 tmpregs (когда MMX не был доступен), с большими предупреждающими комментариями в коде, которые необходимо отладить перед использованием этого трюка.