x86 синтаксическая ошибка логического адреса

0

Компилятор: gcc 4.7.1, 32bit, ubuntu

Вот пример:

    int main(void)
    {
        unsigned int mem = 0;

        __asm volatile
        (
            "mov ebx, esp\n\t"
            "mov %0, [ds : ebx]\n\t"
            : "=m"(mem)
        );

        printf("mem = 0x%08x\n", mem);

        return 0;
    }

gcc -masm=intel -o app main.c

Сообщения ассемблера: invalid use of register!

Как я знаю, ds и ss указывают на один и тот же сегмент. Я не знаю, почему я не могу использовать логический адрес [ds: ebx] для адресации.

Теги:
x86
inline-assembly

1 ответ

2
Лучший ответ

У вашего кода две проблемы:

Один: ссылка косвенной памяти должна быть:

mov %0, ds : [ebx]

То есть, с ds из скобок.

Два: вы используете ограничение памяти (=m) для обращения к переменной mem. Это невозможно, потому что это локальная переменная и, как таковая, не имеет фиксированного адреса. Более того, одна команда не может иметь как начало, так и пункт назначения в памяти, вы должны использовать регистр. Самый простой способ - указать =g что в основном означает что угодно, но в вашем случае это невозможно, потому что esp нельзя перенести непосредственно в память. Вы должны использовать =r.

Три: (?) Вы клонируете ebx, поэтому вы должны объявить его как таковой или иначе не использовать его таким образом. Это не помешает компиляции, но заставит ваш код вести себя беспорядочно.

Вкратце:

  unsigned int mem = 0;
  __asm volatile
  (
    "mov ebx, esp\n\t"
    "mov %0, ds : [ebx]\n\t"
    : "=r"(mem) :: "ebx"
  );

Или лучше не ebx использовать ebx, пусть вместо этого компилятор решит:

  unsigned int mem = 0, temp;
  __asm volatile
  (
    "mov %1, esp\n\t"
    "mov %0, ds : [%1]\n\t"
    : "=r"(mem) : "r"(temp)
  );

Кстати, вам не нужно ключевое слово volatile в этом коде. Это используется для предотвращения оптимизации ассемблера, даже если выход не нужен. Если вы напишете код для побочного эффекта, добавьте volatile, но если вы напишете код для получения результата, не добавляйте volatile. Таким образом, если оптимизирующий компилятор определяет, что выход не нужен, он удалит весь блок.

  • 0
    совершенно верно, спасибо.
  • 0
    Ключевое слово volatile также запрещает компилятору перемещать или переупорядочивать код сборки относительно другого кода (например, выводить его из цикла).

Ещё вопросы

Сообщество Overcoder
Наверх
Меню