Я нашел множество тем об этом теневом пространстве, но не смог найти ответ ни в одной из них, поэтому мой вопрос:
Сколько именно байтов мне нужно вычесть из указателя стека перед входом в процедуру?
И нужно ли помещать параметры процедуры в стек, прежде чем вычесть «пространство тени»?
Я разобрал свой код, но не смог найти логику.
Теневое пространство (также иногда называется Разлить пространство или же Домашнее пространство) предназначен для облегчения отладки x64.
Напомним, что первые 4 параметра передаются в регистрах. Если вы взломаете отладчик и проверите стек вызовов на предмет наличия потока, вы не сможете увидеть какие-либо параметры, переданные функциям. Значения, хранящиеся в регистрах, являются временными и не могут быть восстановлены при перемещении вверх по стеку вызовов.
Это где Домашнее пространство вступает в игру: он может использоваться компиляторами, чтобы оставить копию значений регистра в стеке для последующей проверки в отладчике. Обычно это происходит для неоптимизированных сборок. Однако когда оптимизация включена, компиляторы обычно обрабатывают Домашнее пространство как доступно для использования с нуля. В стеке не осталось копий, а отладка аварийного дампа превращается в кошмар.
Проблемы отладки оптимизированного кода x64 предлагает подробную информацию по этому вопросу.
Теневое пространство — это обязательные 32 байта (4×8 байтов), которые вы должны зарезервировать для вызываемой процедуры. Это просто означает, что вы должны предоставить 32 байта в стеке перед вызовом. Это пространство можно оставить неинициализированным, это не имеет значения.
Обратите внимание, что в соглашении о вызовах x64 аргументы после четвертого помещаются в стек, который находится поверх этого теневого пространства (перед 32 байтами).
Короче говоря, вы можете видеть, что функции в x64 имеют как минимум 4 аргумента, но со значением 4, первым в регистрах.
Такие вещи, как выравнивание стека, также должны учитываться при вызове x64.