Нужно ли резервировать пространство стека для функций менее четырех аргументов? - PullRequest
18 голосов
/ 12 сентября 2011

Я только начал изучать сборку x64, и у меня возник вопрос о функциях, аргументах и ​​стеке.Насколько я понимаю, первые четыре аргумента в функции передаются в регистры rcx, rdx, r8 и r9 (и xmm0-xmm3 для float) в Windows.Таким образом, тривиальная функция сложения с четырьмя параметрами будет выглядеть следующим образом:

add:
   mov r10, rcx
   add r10, rdx
   add r10, r8
   add r10, r9
   mov rax, r10
   ret

Тем не менее, я натолкнулся на документацию , в которой упоминается это :

Как минимум, каждая функция должна зарезервировать в стеке 32 байта (четыре 64-разрядных значения). Это пространство позволяет легко копировать регистры, передаваемые в функцию, в известное место в стеке. Функция вызываемого абонента не требуется, чтобы вылить параметры входного регистра в стек, но резервирование пространства стека гарантирует, что это возможно при необходимости.

Итак, нужно ли мнезарезервировать место в стеке, даже если выполняемые мной функции принимают четыре параметра или меньше, или это просто рекомендация?

Ответы [ 2 ]

13 голосов
/ 12 сентября 2011

Ваша цитата из части "соглашения о вызовах" в документации. По крайней мере, вам не нужно беспокоиться об этом, если вы не вызываете другие функции из своего кода сборки. Если вы это сделаете, то вы должны уважать, среди прочего, «красную зону» и соображения по выравниванию стека, чтобы указанная вами рекомендация была предназначена для обеспечения.

РЕДАКТИРОВАТЬ: этот пост разъясняет разницу между "красная зона" и "пространство тени".

0 голосов
/ 28 марта 2015

Я просто столкнулся с этим, не зная, и, похоже, это так.Например, первые две инструкции в GetAsyncKeyState перезаписывают стек выше возвращаемого значения в области байтов 0x20, которую вы должны зарезервировать для вызываемого абонента для использования в качестве параметров:

user32.GetAsyncKeyState  - mov [rsp+08],rbx
user32.GetAsyncKeyState+5- mov [rsp+10],rsi
user32.GetAsyncKeyState+A- push rdi
user32.GetAsyncKeyState+B- sub rsp,20
...