Какие регистры должны быть сохранены функцией x86? - PullRequest
13 голосов
/ 07 марта 2012

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

В настоящее время я только восстанавливаюesp и ebp, в то время как возвращаемое значение находится в eax.

Есть ли какие-либо другие регистры, о которых я должен беспокоиться, или я могу оставить в них то, что мне нравится?

Ответы [ 3 ]

12 голосов
/ 07 марта 2012

Используя 32-битный ABI от Microsoft (cdecl или stdcall или другие соглашения о вызовах), EAX, EDX и ECX - это чистые регистры (с прерыванием вызова).Остальные целочисленные регистры общего назначения сохраняются при вызове.

Коды условий в EFLAGS являются замкнутыми при вызове.При вызове / возврате требуется DF = 0, поэтому вы можете использовать rep movsb без cld.Стек x87 должен быть пустым при вызове или при возврате из функции, которая не возвращает значение FP.(Возвращаемые значения FP идут в st0, при этом стек x87 пуст, кроме этого.) XMM6 и 7 сохраняются при вызове, остальные - это незаполненные регистры при вызове.

За пределами Windows большинство 32-соглашения о вызовах битов (в том числе i386 System V в Linux) согласуются с этим выбором EAX, EDX и ECX в качестве системного вызова, но все регистры xmm являются системными вызовами.


Для x64 под Windows требуется только восстановить RBX, RBP, RDI, RSI, R12, R13, R14 и R15.XMM6..15 сохраняются по вызову.(И вам нужно зарезервировать 32 байта теневого пространства для использования вызываемым абонентом, независимо от того, есть ли какие-либо аргументы, которые не помещаются в регистры.) Xmm6..15 сохраняются при вызове.
См. https://en.wikipedia.org/wiki/X86_calling_conventions#Microsoft_x64_calling_convention для получения более подробной информации.

Другие операционные системы используют x86-64 System V ABI (см. Рисунок 3.4) , где целочисленные регистры с сохранением вызова - RBP, RBX,RSP, R12, R13, R14 и R15.Все регистры XMM / YMM / ZMM являются замкнутыми при вызове.

EFLAGS и стек x87 такие же, как в 32-разрядных соглашениях: DF = 0, флаги условий помечены, а стек x87 пуст.(Соглашения x86-64 возвращают значения FP в XMM0, поэтому регистры стека x87 всегда должны быть пустыми при вызове / возврате.)


Для ссылок на официальные документы соглашений о вызовах,см https://stackoverflow.com/tags/x86/info

8 голосов
/ 07 марта 2012
32-bit: EBX, ESI, EDI, EBP
64-bit Windows: RBX, RSI, RDI, RBP, R12-R15, XMM6-XMM15
64-bit Linux,BSD,Mac: RBX, RBP, R12-R15

Подробнее см. " Ресурсы для оптимизации программного обеспечения " от Agner Fog.Соглашения о вызовах описаны в этом pdf .

1 голос
/ 09 августа 2015

Если вы не уверены в ситуации с регистрами, приведенные ниже инструкции могут легко спасти день.

PUSHA / PUSHAD - выдвинуть все общие регистры
POPA / POPAD - Pop все общие регистры

Эти инструкции выдвигают и выдвигают регистры общего назначения и регистры SI / ESI, DI / EDI в определенном порядке.

Порядок инструкций PUSHA / PUSHAD следующий.

Opcode  Instruction  Clocks   Description

60      PUSHA        18       Push AX, CX, DX, BX, original SP, BP, SI, and DI
60      PUSHAD       18       Push EAX, ECX, EDX, EBX, original ESP, EBP ESI, and EDI

А порядок инструкций POPA / POPAD следующий. (в обратном порядке)

Opcode   Instruction   Clocks   Description

61       POPA          24       Pop DI, SI, BP, SP, BX, DX, CX, and AX
61       POPAD         24       Pop EDI, ESI, EBP, ESP(***),EBX, EDX, ECX, and EAX

*** Значение ESP сбрасывается, а не загружается в ESP.

...