Ошибка линковки проекта c++

101
07 декабря 2021, 14:40

Писал программу для перевода чисел из DEC в HEX и наоборот разными функциями на Windows с помощью MVS, теперь пришла пора перенести программу на линукс, однако я встретился с неразрешимой проблемой.

/usr/bin/ld: ./Source.o: relocation R_X86_64_32S against undefined symbol `n' can not be used when making a PIE object; перекомпилируйте с параметром -fPIC Компилировать через консоль с параметром -fPIC проблвал, не помогло, в настройках проекта параметр указывал.

Кстати изначально программа была написана для х32 версии|, ещё на винде, а здесь убунта х64.

Версии: Ubuntu 18.04.3 LTS х64

g++ (Ubuntu 7.4.0-1ubuntu1~18.04.1) 7.4.0

Eclipse IDE for C/C++ Developers Version: 2019-09 R (4.13.0) Build id: 20190917-1200

Выкладываю код:

#include <iostream>
#include <cstring>
#include <string>
using namespace std;
enum
{
   CMD_FLOAT_TO_HEX,
   CMD_DOUBLE_TO_HEX,
   CMD_HEX_TO_FLOAT,
   CMD_HEX_TO_DOUBLE,
   CMD_EXIT
};
template<typename in, typename out>
out Asm1(in n)  // FLOAT / DOUBLE -> HEX
{
   out res;
   asm
   (
      "fld n;"
      "fstp res;"
   );
   return res;
}
template<typename in, typename out>
out Asm2(in n)  // HEX -> FLOAT / DOUBLE
{
   out res;
   asm
   (
      "movsd %xmm0, n;"
      "movsd res, %xmm0;"
   );
   return res;
}
template<typename in, typename out>
out Memcpy(in n)
{
   out res;
   memcpy(&res, &n, sizeof(in));
   return res;
}
template<typename in, typename out>
out Cast(in n)
{
   return *reinterpret_cast<out*>(&n);
}
template<typename in, typename out>
out Union(in n)
{
   union
   {
      in _n;
      out _res;
   };
   _n = n;
   return _res;
}

int main()
{
   int n;
   cout << "<0> - float to hex" << endl;
   cout << "<1> - double to hex" << endl;
   cout << "<2> - hex to float" << endl;
   cout << "<3> - hex to double" << endl;
   cout << "<4> - exit" << endl << endl;
   do
   {
      cout << "choose command (from 0 to 4): ";
      cin >> n;
      cout << endl;
      switch (n)
      {
      case CMD_FLOAT_TO_HEX:
         float f1;
         cout << "write a number: ";
         cin >> f1;
         cout << "\na float number " << f1 << " in hex:\t0x"   << hex << Memcpy<float, int>(f1) << " (MEMCPY)" << endl;
         cout << "\t\t\t\t0x"                                  << hex << Cast<float, int>(f1)   << " (REINTERPRETER_CAST)" << endl;
         cout << "\t\t\t\t0x"                                  << hex << Union<float, int>(f1)  << " (UNION)" << endl;
         cout << "\t\t\t\t0x"                                  << hex << Asm1<float, int>(f1)   <<  " (__ASM) "<<endl;
         cout << endl;
         break;
      case CMD_DOUBLE_TO_HEX:
         double d1;
         cout << "write a number: ";
         cin >> d1;
         cout << "\na double number " << d1 << " in hex:\t0x"  << hex << Memcpy<double, long long>(d1) << " (MEMCPY)" << endl;
         cout << "\t\t\t\t0x"                                  << hex << Cast<double, long long>(d1)   << " (REINTERPRETER_CAST)" << endl;
         cout << "\t\t\t\t0x"                                  << hex << Union<double, long long>(d1)  << " (UNION)" << endl;
         cout << "\t\t\t\t0x"                                  << hex << Asm1<double, long long>(d1)   << " (__ASM) " << endl;
         cout << endl;
         break;
      case CMD_HEX_TO_FLOAT:
         uint32_t f2;
         cout << "write a hex: ";
         cin >> hex >> f2;
         cout << "\na hex 0x" << hex << f2 << " is equal to float\t"   << Memcpy<int, float>(f2) << " (MEMCPY)" << endl;
         cout << "\t\t\t\t\t"                                          << Cast<int, float>(f2)   << " (REINTERPRETER_CAST)" << endl;
         cout << "\t\t\t\t\t"                                          << Union<int, float>(f2)  << " (UNION)" << endl;
         cout << "\t\t\t\t\t"                                          << Asm2<int, float>(f2)   << " (__ASM) " << endl;
         cout << endl;
         break;
      case CMD_HEX_TO_DOUBLE:
         uint64_t d2;
         cout << "write a hex: ";
         cin >> hex >> d2;
         cout << "\na hex 0x" << hex << d2 << " is equal to double\t"  << Memcpy<long long, double>(d2) << " (MEMCPY)" << endl;
         cout << "\t\t\t\t\t\t"                                        << Cast<long long, double>(d2)   << " (REINTERPRETER_CAST)" << endl;
         cout << "\t\t\t\t\t\t"                                        << Union<long long, double>(d2)  << " (UNION)" << endl;
         cout << "\t\t\t\t\t\t"                                        << Asm2<long long, double>(d2)   << " (__ASM) " << endl;
         cout << endl;
         break;
      case CMD_EXIT:
         break;
      default:
         cout << "wrong command" << endl;
         cout << endl;
         break;
      }
   } while (n != CMD_EXIT);
   return 0;
}
Answer 1

Ассемблер в GCC так не работает.

Ассемблер в GCC не поддерживает прямого обращения к локальным переменным по именам. Всякий раз, когда вы пишете что-то вроде "fld n;", компилятор рассматривает это как обращение к глобальной переменной n и передает его на рассмотрение линкеру. Линкер, разумеется, не находит никакой глобальной переменной n, что и приводит к ошибке.

Локальные переменные нужно вручную описывать в ассемблерном блоке как входные и выходные операнды, через специальный синтаксис. См. пример здесь и документацию здесь.

Например

float Asm1(double n)
{
   float res;
   asm 
   (
      "fldl %1;"
      "fstps %0;"
      : "=m" (res) : "m" (n) 
   );
   return res;
}

При этом надежды на то, что в вашем исходном варианте ассемблерный код с fld и fstp поведет себя "по шаблонному" и будет генерировать правильную команду для каждого размера операнда не оправдались. В ассемблере GCC fld и fstp просто тупо эквивалентны flds и fstps. Для того, чтобы ваш шаблон с параметрами Asm1<double, float> работал правильно, придется все равно явно указывать fldl, как у меня в примере выше. То есть вся ваша затея с таким ассемблерным кодом внутри шаблона - не работает.

READ ALSO
Отображает непонятные символы c++

Отображает непонятные символы c++

Пытаюсь сделать поиск участников из существующего файла, но отображает изначально непонятные цифры, в следствии чего как я подозреваю не дает...

76
С++ bass dll кириллица

С++ bass dll кириллица

Делаю свой плеер на C++ OpenGL Bass dll

80
Нестандартная инициализация for [дубликат]

Нестандартная инициализация for [дубликат]

Когда изучал строки и векторы, наткнулся на вывод вектора таким образом

73
Проблемы с тестом глубины OpenGL

Проблемы с тестом глубины OpenGL

Только начал заниматься с OpenGL и столкнулся с проблемами с тестом глубиныИспользую шейдеры для текстурированного GL_POLYGON и нескольких of GL_LINE_STRIP

92