Мне нужно вставить указатель в EAX и один в регистр EBX. Я сначала решил это с:
register int eax asm("eax");
register int ebx asm("ebx");
int main()
{
eax = ptr1;
ebx = ptr2;
}
Который работал как шарм. Однако, когда я добавил это в свой другой код, я получил некоторые странные ошибки о том, что gcc не может найти регистр для разлива в классе AREG, в совершенно не связанной части кода. Я гуглил, и оказалось, что это действительно ошибка в gcc -.-. Итак, мне нужен другой способ, чтобы вставить два указателя в регистры eax и ebx. У кого-нибудь есть идеи? Спасибо!
редактировать, так как люди спрашивают, что я пытаюсь сделать здесь, я подумал, что объясню немного.
Мне нужно изменить eax и ebx для некоторого ассемблерного кода, который я пытаюсь запустить в своей программе. Мне нужно выполнить этот ассемблерный код и дать указатель на параметр через регистры eax и ebx. Я выполняю ассемблерный код, нажимая указатель на него в ebx и вызывая ebx. Когда я не вызываю регистр, глобально, но локально, код ассемблера падает. Если я вызываю это глобально, я получаю эту странную ошибку в конце случайной функции. Когда я удаляю эти функции, он выдает ту же ошибку в другую случайную функцию. Пока у меня не закончились функции, тогда это работает, но потом я скучаю по остальной части кода: P
Если у вас есть (встроенный) код сборки, который требует определенных параметров в EAX
/EBX
способ сделать это в gcc — использовать следующее:
__asm__("transmogrify %0, %1\n" : "+a"(val_for_eax), "+b"(val_for_ebx));
Это использует то, что gcc называет встроенной сборкой ограничения которые сообщают компилятору, что код сборки — какой бы он ни был — ожидает val_for_eax
/val_for_ebx
в EAX
/EBX
(это a
/b
часть), а также что он будет возвращать потенциально измененные версии этих переменных (это +
) в этих регистрах также.
Помимо этого, фактический код в пределах asm()
оператор не имеет значения для компилятора — ему нужно / нужно только знать, где параметры %0
а также %1
жить. Приведенный выше пример из-за transmogrify
инструкция, не существующая в текущем наборе команд x86, завершается ошибкой при выполнении ассемблера; просто замените это чем-то действительным.
Объяснение того, почему gcc ведет себя так и что именно вы можете сказать, приведено в руководстве GCC по адресу:
asm
операнды, в частности, раздел Intel / 386 Список машинно-зависимых ограничений что сказать, если вам нужно передать / получить значение в определенном регистре, и Модификаторы раздел о значении таких вещей, как +
(и для передачи, и для возврата значения; есть другие подобные «модификаторы» для ограничений)Вы можете указать конкретный регистр для переменной, но из-за того, как работает gcc / как встроенная сборка реализована в gcc, делая это не значит (!) регистр с тех пор зарезервированный (вне области видимости) для gcc для использования в своих собственных целях. Это может быть достигнуто только с помощью ограничений, для asm()
block — ограничения сообщают gcc, что записывать в эти регистры до размещение фактического кода сборки и что читать с них впоследствии.
Так как eax
регистр необходим везде в действующей программе вашей архитектуры, ваша стратегия не может работать с глобальными переменными, которые связаны с конкретными регистрами. Не делайте этого, резервировать регистр по всему миру не очень хорошая идея.
Поместите переменные, которые связаны с регистрами в конкретной функции, как можно ближе к их использованию.