Как сохранить состояние регистров при создании функции cdecl?

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

Мой вопрос в том, как это обычно выполняется. Это просто вопрос помещения регистров в стек в начале функции и последующего извлечения их в регистры в конце функции?


person Community    schedule 08.01.2015    source источник
comment
Да, push/pop работает. Конечно, вы также можете сохранить их в явных локальных переменных. Я предполагаю, что вы знаете, что вам не нужно сохранять все регистры.   -  person Jester    schedule 08.01.2015
comment
Да, некоторые из них — вызывающим абонентом, другие — вызываемым, см. здесь en.wikipedia.org/ wiki/X86_calling_conventions#cdecl   -  person zx485    schedule 08.01.2015


Ответы (1)


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

Как вы, наверное, знаете, вы можете делать с EAX, ECX и EDX все, что хотите, но вам нужно будет сохранить практически все остальное

Мой вопрос в том, как это обычно выполняется. Это просто вопрос помещения регистров в стек в начале функции и последующего извлечения их в регистры в конце функции?

Да, обычно так и делается. PUSH все в начале, POP перед возвращением.

Но иногда может иметь смысл использовать вместо этого регистр, сохраненный вызывающей стороной. Допустим, вы никогда не используете EDX в своей функции и не вызываете никакую функцию так, чтобы это могло затронуть ее содержимое. Но вы хотите использовать EDI в своей функции. Вы можете сохранить EDI в стеке или сохранить его в EDX.

mov edx, edi
; Do something with EDI without corrupting EDX, e.g. string manipulation
mov edi, edx

вместо

push edi
; Do something with EDI, e.g. string manipulation
pop edi

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

Обратите внимание, что вам не нужно необходимо сохранять все в самом начале и восстанавливать непосредственно перед возвратом. Вы можете сохранить регистр прямо перед тем, как использовать его, и восстановить его, как только закончите с ним работать, в середине функции.

person tux3    schedule 08.01.2015