Ответ 1
"Красная зона" не является строго необходимой. В ваших терминах это можно считать "бессмысленным". Все, что вы могли бы сделать, используя красную зону, вы также можете сделать традиционный способ, которым вы это сделали, нацеливаясь на IA-32 ABI.
Здесь AMD64 ABI говорит о "красной зоне":
128-байтовая область за пределами местоположения, на которую указывает
%rsp
, считается зарезервированной и не должна изменяться обработчиками сигналов или прерываний. Поэтому функции могут использовать эту область для временных данных, которые не нужны для вызовов функций. В частности, функции листьев могут использовать эту область для всего кадра стека, а не корректировать указатель стека в прологе и эпилоге. Эта область называется красной зоной.
Реальная цель красной зоны - это оптимизация. Его существование позволяет коду предположить, что 128 байтов ниже rsp
не будут асинхронно сбиты сигналами или обработчиками прерываний, что позволяет использовать его в качестве пространства скреста. Это делает ненужным явно создавать пространство царапин в стеке, перемещая указатель стека в rsp
. Это оптимизация, потому что теперь можно удалить инструкции для уменьшения и восстановления rsp
, экономя время и пространство.
Итак, да, хотя вы можете сделать это с помощью AMD64 (и нужно будет делать это с IA-32):
function:
push rbp ; standard "prologue" to save the
mov rbp, rsp ; original value of rsp
sub rsp, 32 ; reserve scratch area on stack
mov QWORD PTR [rsp], rcx ; copy rcx into our scratch area
mov QWORD PTR [rsp+8], rdx ; copy rdx into our scratch area
; ...do something that clobbers rcx and rdx...
mov rcx, [rsp] ; retrieve original value of rcx from our scratch area
mov rdx, [rsp+8] ; retrieve original value of rdx from our scratch area
add rsp, 32 ; give back the stack space we used as scratch area
pop rbp ; standard "epilogue" to restore rsp
ret
нам не нужно делать это в тех случаях, когда нам нужна только область с 128-байтовым царапинам (или меньше), потому что тогда мы можем использовать красную зону в качестве нашей области царапин.
Плюс, поскольку нам больше не нужно уменьшать указатель стека, мы можем использовать rsp
в качестве базового указателя (вместо rbp
), что делает ненужным сохранение и восстановление rbp
(в прологе и эпилоге), а также освобождение rbp
для использования в качестве другого универсального регистра!
(Технически, включение бездействия кадрового указателя (-fomit-frame-pointer
, включенное по умолчанию с помощью -O1
, поскольку ABI позволяет это) также позволит компилятору преодолеть разделы пролога и эпилога с теми же преимуществами Однако, если отсутствует красная зона, необходимость корректировать указатель стека на резервное пространство не изменится.)
Обратите внимание, однако, что ABI гарантирует, что асинхронные вещи, такие как сигналы и обработчики прерываний, не изменяют красную зону. Звонки на другие функции могут иметь значение clobber в красной зоне, поэтому это не особенно полезно, кроме функций листа (которые те функции, которые не вызывают никаких других функций, как если бы они находились в "листе" дерева функций).
Конечная точка: Windows x64 ABI немного отклоняется от AB64 AMD64, используемого на другом операционных систем. В частности, он не имеет понятия о "красной зоне". Площадь за пределами rsp
считается изменчивой и может быть перезаписана в любое время. Вместо этого он требует, чтобы вызывающий абонент выделял домашнее адресное пространство в стеке, которое затем доступно для использования вызываемого абонента в случае необходимости для разлива любого из параметров, прошедших регистрацию.