2016-11-12 8 views
2

У меня есть проект, который полностью написан на C. Эти же C-файлы могут быть скомпилированы с использованием GCC для Linux или MSVC для Windows. По соображениям производительности мне нужно перезаписать часть кода как язык ассемблера x86.Могу ли я написать (x86) язык ассемблера, который будет построен как с GCC, так и с MSVC?

Можно ли написать этот язык ассемблера в качестве исходного файла, который будет построен как с инструментами GCC, так и с MSVC? В качестве альтернативы, если я пишу исходный файл сборки для одной инструментальной цепочки, есть ли инструмент для его преобразования для работы с другим?

Или я застрял либо с сохранением двух копий исходного кода сборки, либо с помощью стороннего ассемблера, такого как NASM?

+2

Вы спрашиваете, потому что вы triend и потерпели неудачу, или потому что вы расследовали и не нашли окончательного ответа? Знаете ли вы, что между этими двумя? – usr2564301

+0

Мы говорим о 32-битной или 64-битной сборке? – fuz

+0

Встроенная сборка или нет? – Banex

ответ

4

Я вижу две проблемы:

  • MASM и газа имеют различный синтаксис. газ может быть сконфигурирован для использования синтаксиса Intel с директивой .syntax intel,noprefix, но даже тогда остаются небольшие различия (например, разные директивы). Возможный подход состоит в том, чтобы предварительно обработать ваш источник сборки препроцессором C, используя макросы для всех директив, которые отличаются друг от друга. Это также имеет преимущество в предоставлении единого синтаксиса комментариев.

    Однако использование портативного стороннего ассемблера, такого как nasm, скорее всего, будет сопряжено с трудностями.

  • Linux и Windows имеют разные соглашения о вызовах. Возможным решением для x86-32 является придерживаться хорошо поддерживаемого соглашения о вызове, например, stdcall. Вы можете указать gcc, какое соглашение о вызове использовать при вызове функции, используя function attributes. Например, это объявить бы foo использовать stdcall соглашение о вызовах:

    extern int foo(int x, int y) __attribute__((stdcall)); 
    

    Вы можете сделать то же самое в MSVC с __declspec, решение этой проблемы.

    На x86-64 похожее решение, вероятно, возможно, но я не совсем уверен, какие атрибуты вы должны установить.

    Возможно, вы также используете тот же подход cpp, что и для первой проблемы, чтобы генерировать несколько разных пролог функций и эпилогов в зависимости от того, какое соглашение о вызовах вам нужно. Однако это может быть менее ремонтопригодным.

+0

В 32-битном x86 было бы разумнее придерживаться стандартного соглашения о вызовах «cdecl», что и на Linux, и на Linux. –

+0

Итак, была ли ваша рекомендация использовать сторонний ассемблер? Так как другие проекты (которые содержат язык ассемблера и поддерживают несколько операционных систем), как правило, решают эту проблему? – user200783

+0

@ user200783 В основном, когда C-код возвращается, когда данный процессор не поддерживается или данный ассемблер недоступен. –