64-битные проблемы: попытка скопировать значение из %rsp во временную переменную с помощью встроенной сборки

Я посещаю занятия по проектированию операционных систем, на которых нам дали микроядро, написанное на языке C, на основе которого мы строим. Ядро, кажется, было разработано с учетом 32-битных машин, и я использую Snow Leopard. Итак, мы с другом в классе пытались взломать его до 64-битной адресации.

Самая большая проблема, по-видимому, заключается в одной строке кода, где встроенный ассемблер используется для копирования текущего указателя стека во временную переменную, используемую диспетчером:

#define SET_STACK(s) asm("movl temp,%esp");

Естественно, компилятор выдает мне ошибки, потому что %esp — 32-битный регистр.

/var/folders/0A/0AVWZC-5HhOg6twWZBlDgU+++TI/-Tmp-//cckS2oq7.s:523:32-bit absolute addressing is not supported for x86-64
/var/folders/0A/0AVWZC-5HhOg6twWZBlDgU+++TI/-Tmp-//cckS2oq7.s:523:cannot do signed 4 byte relocation

Поэтому я заменил его на %rsp, потому что это 64-битный регистр указателя стека (и я думаю, что просто %sp тоже работает, я где-то читал здесь, что GAS достаточно умен, чтобы поставить правильный префикс). После замены %esp на %rsp я получаю эту ошибку:

/var/folders/0A/0AVWZC-5HhOg6twWZBlDgU+++TI/-Tmp-//cc8TLdjH.s:523:Incorrect register `%sp' used with `l' suffix

Теперь я немного в растерянности, потому что я не очень разбираюсь в ассемблере. Я пытался заменить movl на mov и movq, но ничего не работает. Что наводит меня на мысль, что, возможно, temp неправильный размер?

Temp — это глобальная переменная, объявленная так:

void* temp;   // temp pointer used in dispatcher

Я написал быструю программу для вывода размеров различных типов данных, и кажется, что void* в x86-64 имеет размер 8 байтов, что должно быть правильным размером, верно?

В любом случае, очевидно, я не ожидаю, что кто-то решит эту проблему за меня, но любые советы, которые могут указать мне правильное направление, будут высоко оценены!


person Jarsen    schedule 24.06.2010    source источник


Ответы (2)


Вам нужно использовать movq для 64-битных перемещений.

Вот фрагмент сборки, выполняющей некоторую работу SSE из одного из моих проектов (часть симулятора поезда). Закомментированные строки - это 32-битный Intel asm, раскомментированные - 64-битный AT&T.

asm(
        //mykda calculation
        //mov eax, dword ptr [train_traction_ptr]
        //movaps xmm0, xmmword ptr [eax] //train_traction[i] + forceFront
        "movq %0, %%rax\n\t"
        "movaps (%%rax), %%xmm0\n\t"

        //mov eax, dword ptr [local_fgrr_ptr]
        //movaps xmm1, xmmword ptr [rax]
        //addps xmm0, xmm1
        "movq %1, %%rax\n\t"
        "movaps (%%rax), %%xmm1\n\t"
        "addps %%xmm1, %%xmm0\n\t"

        ... );

После комментария я посмотрел дальше и обнаружил, что весь 64-битный код OSX должен быть независимым от позиции.

У меня нет Mac для тестирования, но

asm ("movq temp(%rip),%rsp");

Должно сработать. Если нет, вам нужно использовать соответствующую адресацию PIC для temp для вашего ассемблера.

person Hayman    schedule 24.06.2010
comment
Спасибо за ответ. На самом деле я пробовал movq, но все еще получаю следующую ошибку от gcc: для x86-64 /var/folders/0A/0AVWZC-5HhOg6twWZBlDgU+++TI/-Tmp-//cc7VMqAZ.s:523:невозможно выполнить перемещение 4 байтов со знаком. не переместить его в %rsp? - person Jarsen; 24.06.2010
comment
Я попробовал это, и это не сработало, но спросило меня, имел ли я в виду _temp, поэтому я предположил, что да. И это, похоже, решило проблему: asm (movq _temp(%rip),%rsp); Так что большое спасибо! На данный момент работает, надеюсь, я не столкнусь с чем-то неприятным позже. Просто для моей же пользы, если у вас все еще есть URL-адрес или что-то еще, где вы нашли эту информацию, не могли бы вы дать ее мне? Спасибо большое. - person Jarsen; 24.06.2010
comment
Не беспокойся, чувак. В частности, это был один URL — lists.apple.com/archives. /xcode-users/2006/Sep/msg00060.html Если вы погуглите об ошибке абсолютной адресации, там много сообщений на форуме. Я предполагаю, что у Apple где-то будет какая-то документация, хотя я не нашел ее в своем поиске. - person Hayman; 25.06.2010

Показанная вами строка не копирует значение из %esp в temp, а наоборот (как подразумевает SET_STACK). Синтаксис AT&T: src, dest.

Простой asm("mov temp, %rsp"); должен скомпилироваться.

person caf    schedule 24.06.2010
comment
Ха, приятно знать, что у меня было это задом наперёд. Спасибо. На самом деле я пробовал mov и только что попробовал еще раз, но он все еще дает мне это: адресация не поддерживается для x86-64 подходит ли размер для перехода в %rsp? - person Jarsen; 24.06.2010
comment
... подписанное 4-байтовое перемещение... заставьте меня задуматься о выравнивании... возможно? может быть, void*temp следует выровнять по четырем (четверным, я имею в виду, 64-битным)? ... но 32-bit absolute addressing is not supported for x86-64 заставляет меня думать, что по какой-то причине он считает temp 32-битным абсолютным адресом (почему так должно быть? это не должно...); интересно, увы, нет 64-битной машины, чтобы делать тесты - person ShinTakezou; 24.06.2010