Размер кадра стека, когда я вставляю новые инструкции для сборки x86?
Если я вставляю новые функции и инструкции, которые в кадре стека, для сборки кода x86, необходимо ли увеличивать размер стека? если да на сколько?
sub 0x4, %esp
push %eax ;;new instruction
...
call fun ;; new inserted function
pop %eax ;;new instruction
.....
add 0x4, %esp
1 ответ
Соглашения о вызовах - это ключ к управлению вызовом функций, передачей и возвратом значений и управлением пространством стека и доступными регистрами. Там много соглашений. Знайте, какую функцию использует ваша функция, а какую использует функция, которую вы вызываете; они могут быть разными!
Очень распространенное соглашение - "управляй своим стеком". В этом случае каждая функция выделяет количество стекового пространства, которое ей необходимо в стеке. Не нужно беспокоиться о требованиях к пространству стека функций, которые он вызывает; по определению они будут выделять (дополнительное) количество места в стеке, которое им нужно.
"Листовая" функция - это функция, которая не вызывает никаких других функций; каждая листовая функция требует некоторого количества стекового пространства. Некоторые соглашения о вызовах требуют, чтобы вызывающая функция конечной функции выделяла не только пространство для собственных нужд, но и всех конечных функций для своих вызовов. Это сводит к минимуму накладные расходы на вызов листовых функций (которые вызываются чаще всего!). Обычно такого рода компоновка выполняется только компилятором, поскольку людям трудно надежно отслеживать все вызываемые ими функции и требования к стеку этих функций. Иногда вы можете встретить рукописную функцию сборки, которая в качестве части своего API заявляет, что вызывающая сторона должна выделить для нее место.
System V ABI предлагает "красную зону" размером около 128 байт стека ниже SP, которая всегда доступна для конечной функции. Это означает, что вызывающей стороне не нужно выделять это пространство, и конечные функции с меньшим, чем требуется по размеру красной зоны, просто имеют его в наличии, не выделяя его. Это очень хорошее соглашение, потому что ни одна функция не должна беспокоиться о том, вызывает ли она конечную функцию или нет, и это позволяет связывать произвольные наборы подпрограмм вместе.