GCC не сохраняет / восстанавливает зарезервированные регистры при вызовах функций - PullRequest
2 голосов
/ 28 июля 2011

У меня есть сценарий в GCC, который вызывает у меня проблемы.Поведение, которое я получаю, - это не то поведение, которого я ожидаю.Чтобы подвести итог ситуации, я предлагаю несколько новых инструкций для x86-64, которые реализованы в аппаратном симуляторе.Чтобы проверить эти инструкции, я беру существующий исходный код на C и вручную пишу новые инструкции, используя шестнадцатеричный код.Поскольку эти инструкции взаимодействуют с существующими регистрами x86-64, я использую списки ввода / вывода / clobber для объявления зависимостей для GCC.

Что происходит, если я вызываю функцию, например printf, зависимые регистры не 't сохранено и восстановлено.

Например,

register unsigned long r9  asm ("r9")  = 101;
printf("foo %s\n", "bar");
asm volatile (".byte 0x00, 0x00, 0x00, 0x00" : /* no output */ : "q" (r9) );

101 было назначено для r9, а встроенная сборка (в данном примере fake) зависит от r9.Это работает правильно при отсутствии printf, но когда он есть, GCC не сохраняет и не восстанавливает r9, и к тому времени, когда вызывается моя пользовательская инструкция, появляется другое значение.

Возможно, я подумал, что GCC мог тайноизменил присвоение переменной r9, но когда я делаю это

asm volatile (".byte %0" : /* no output */ : "q" (r9) );

и смотрю на вывод сборки, он действительно использует% r9.

Яиспользуя gcc 4.4.5.Как вы думаете, что может происходить?Я думал, что GCC всегда будет сохранять и восстанавливать регистры при вызовах функций.Есть ли способ, которым я могу обеспечить это?

Спасибо!

РЕДАКТИРОВАТЬ: Кстати, я собираю программу, как это

gcc -static -m64 -mmmx -msse -msse2 -O0 test.c -o test

Ответы [ 2 ]

7 голосов
/ 28 июля 2011

ABI , раздел 3.2.1 гласит:

Регистры% rbp,% rbx и от% r12 до% r15 «принадлежат» к вызывающей функции и вызываемая функция требуется сохранить свои ценности. Другими словами, вызываемая функция должна сохранять значения этих регистров для вызывающей стороны. Остальные регистры «принадлежат» вызываемым функция. Если вызывающая функция хочет сохранить такое значение регистра через вызов функции, он должен сохранить значение в своем локальном кадре стека.

поэтому не следует ожидать, что при вызове функции будут сохранены регистры, кроме% rbp,% rbx и% r12 -% r15.

2 голосов
/ 28 июля 2011

gcc не будет создавать переменные с явным регистром, такие как сохраненные.По сути, эта используемая вами запись регистра делает переменную прямым псевдонимом для регистра, исходя из предположения, что вы хотите иметь возможность считывать значение, оставляемое вызываемым пользователем, в регистре.Если бы вы использовали регистр, сохраненный вызывающим абонентом, вместо регистра с сохраненным вызовом (сохраненного вызывающим абонентом), проблема исчезла бы.

...