Что обеспечивает чтение / запись операндов в нужное время с расширенным ASM?

Согласно GCCРасширенный шаблон ASM и ассемблерЧтобы инструкции оставались последовательными, они должны находиться в одном блоке ASM. У меня возникают проблемы с пониманием того, что обеспечивает планирование или время чтения и записи в операнды в блоке с несколькими операторами.

В качестве примера,EBX или жеRBX должен быть сохранен при использованииCPUID потому что, согласно ABI, звонящий владеет им. Есть некоторые открытые вопросы относительно использованияEBX а такжеRBXпоэтому мы хотим сохранить его безоговорочно (это требование). Таким образом, три инструкции должны быть закодированы в один блок ASM, чтобы обеспечить последовательность инструкций (относительно шаблона ассемблера, описанного в первом абзаце):

unsigned int __FUNC = 1, __SUBFUNC = 0;
unsigned int __EAX, __EBX, __ECX, __EDX;

__asm__ __volatile__ (

  "push %ebx;"
  "cpuid;"
  "pop %ebx"
  : "=a"(__EAX), "=b"(__EBX), "=c"(__ECX), "=d"(__EDX)
  : "a"(__FUNC), "c"(__SUBFUNC)

);

Если выражение, представляющее операнды, интерпретируется в неправильный момент времени, то__EBX будет сохраненEBX (а неCPUID«sEBX), который, вероятно, будет указателем на Глобальную таблицу смещений (GOT), если включен PIC.

Где именно выражение указывает, что хранилищеCPUID«s%EBX в__EBX должно произойти (1) послеPUSH %EBX; (2) послеCPUID; но (3) доPOP %EBX?