64-битные проблемы: попытка скопировать значение из% rsp во временную переменную с помощью встроенной сборки - PullRequest
4 голосов
/ 24 июня 2010

Я беру класс проектирования операционных систем, в котором нам дали микроядро, написанное на C, над которым мы строим. Ядро, похоже, было разработано с учетом 32-битных машин, и я использую снежного барса. Итак, друг в классе, и я пытался взломать его на 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 байт, который должен быть правильного размера, верно?

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

Ответы [ 2 ]

2 голосов
/ 24 июня 2010

Строка, которую вы показали, не копирует значение из %esp в temp - она ​​делает наоборот (как следует из SET_STACK). Синтаксис AT & T: src, dest.

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

1 голос
/ 24 июня 2010

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

Вот фрагмент сборки, выполняющий некоторые SSE-работы из одного из моих проектов (часть симулятора поезда).это 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 должен быть независимым от позиции.

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

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

...