Какие-либо ограничения относятся к старшей половине регистра в встроенной сборке gcc? - PullRequest
1 голос
/ 05 апреля 2011

В моем C-коде есть встроенная сборка, вызывающая службу PCI BIOS.Теперь проблема в том, что один из результатов возвращается в регистр %ah, но я не могу найти константу для ссылки на этот регистр.

Я хочу написать так:

asm("lcall *%[call_addr]" : "something here"(status) :);

и переменная status содержит значение регистра %ah.

Если я использую "=a"(status) и добавлю инструкцию mov %%ah, %%al, она будет работать.Но это выглядит некрасиво.

Есть предложения?

1 Ответ

0 голосов
/ 06 апреля 2011

Я не думаю, что есть способ указать %ah в ограничении - бэкэнд GCC x86 знает, что подрегистры содержат определенные части значений, но на самом деле не рассматривает их как независимые объекты.

Ваш подход будет работать;другой вариант - сдвинуть status за пределы встроенного ассемблера.например, это:

unsigned int foo(void)
{
  unsigned int status;

  asm("movb $0x12, %%ah; movb $0x34, %%al" : "=a"(status) : );
  return (status >> 8) & 0xff;
}

... реализует (status >> 8) & 0xff как одну инструкцию movzbl %ah, %eax.

Третий вариант - использовать небольшую структуру:

unsigned int bar(void)
{
  struct { uint8_t al; uint8_t ah; } status;

  asm("movb $0x12, %%ah; movb $0x34, %%al" : "=a"(status) : );
  return status.ah;
}

Я не уверен, что это лучше или нет - кажется немного более самодокументированным, но использование небольшой структуры с ограничением регистра выглядит менее очевидно правильным.Однако он генерирует тот же код, что и foo() выше.

(Отказ от ответственности: генерация кода протестирована только с gcc 4.3.2; результаты могут отличаться в других версиях.)

...