Посмотрите на выход gcc. По умолчанию он равен при оптимизации, только создавая фрейм стека, когда функции используют массивы переменной длины или ему нужно выровнять стек более чем на 16B.
Эта страница wiki в основном неправильная. Там не страшно странно, что делает его «ненадежным». Единственный раз, когда вы не можете этого сделать, - это когда вам нужно изменить RSP на величину, которая не является постоянной времени сборки.
Однако, если вы сделать сделать кадр стека с push rbp
/mov rbp, rsp
, вы должны использовать РБП-относительный режимы адресации. Это более эффективно, потому что [rsp + 8]
берет дополнительный байт для кодирования (против [rbp - 8]
). Режимы адресации с RSP в качестве базового регистра всегда нуждаются в байте SIB, даже если нет индексного регистра.
Точка использования RSP-относительных режимов адресации, что вы можете избежать потерь инструкции сделать кадр стека, так ОПБ это просто еще один вызов сохраняемых регистров (например, RBX), которые вы можете сохранить/восстановить и использовать для любого вы хотите.
Другое большое преимущество ОПБ-относительной адресации является то, что смещение от RBP к данной переменной остается постоянной в течение всей функции. В отличие от компиляторов, мы, мелкие люди, легко путаем толками и попсами, которые меняют RSP внутри функции. Конечно, 64-битный код вряд ли когда-либо изменяет RSP внутри функции между прологом и эпилогом, потому что оба ABI передают аргументы в регистры. Сохранение/восстановление некоторых регистров, сохраняющих код (например, RBX или R12-R15) в прологе/эпилоге, часто лучше, чем нажатие/поп внутри функции (и, безусловно, лучше, чем внутри цикла). Когда вам нужно проливать/перезагружать, mov
для случайного доступа обычно лучше всего.
В 32-битном коде создание фрейма стека в рукописном коде часто имеет смысл, особенно. для ремонтопригодности. В 64-битном коде это обычно не проблема. Хотя сохранение/восстановление дополнительного регистра с дополнительной парой push/pop изменяет структуру стека, что имеет значение, если в стеке были переданы какие-либо аргументы (например, большая структура по значению, но напишите свою функцию, чтобы взять const-указатель arg вместо!).
Указатель стека * может * часто использоваться для определения адреса переменных в стеке.Однако, если функция использует массивы переменной длины или эквивалент 'alloca()', использование смещений из указателя стека может оказаться невозможным. – EOF
@EOF, поэтому следует использовать адресацию по отношению к rsp во всех случаях, кроме двух? –