?

Log in

No account? Create an account
Inline assembly: GCC + Watcom. - Живой Журнал системного программиста
April 8th, 2009
03:40 am

[Link]

Previous Entry Share Next Entry
Inline assembly: GCC + Watcom.
Задумался о кросс-компиляции моего ядрышка GCC (сейчас пока компилируется только Watcom'ом).

Первый большой и краеугольный камень - это, конечно, ассемблерные вставки. Поэтому был придуман механизм, чтобы минимизировать писанину и дублирование ассемблерного кода для обоих компиляторов. С этой целью я сделал некий заголовочный файл, в котором объявил:


#ifdef __WATCOMC__
    // Define Pragmas
    #define inline_func(prag_d, ret_t, body)    ret_t __pragma(#prag_d) body;
    #define inline_proc(prag_d, body)           void  __pragma(#prag_d) body;
#endif /* __WATCOMC__ */

#ifdef __GNUC__
    // Define Pragmas
    #define inline_func(prag_d, ret_t, body)        \
        static __inline ret_t body                  \
        {                                           \
            ret_t __result;                         \
            __asm__ __volatile__ (                  \
                    ".intel_syntax noprefix"        \
                    prag_d                          \
            );                                      \
            return __result;                        \
        }

    #define inline_proc(prag_d, body)               \
        static __inline void body                   \
        {                                           \
            __asm__ __volatile__ (                  \
                    ".intel_syntax noprefix"        \
                    prag_d                          \
            );                                      \
        }
#endif /* __GNUC__ */



Заметим, что для GNU GCC я заведомо врубил синтаксис интела (ну не люблю я синтаксис AT&T, да и нафиг он не нужен на i386, на мой взгляд).

Теперь, допустим, захотел я сделать функцию __strlen на ассемблере. Для этого я ворочу соответствующие макросы:


#define __I386_STREND_IMPL          \
        "mov    ecx, -1"            \
        "xor    al, al"             \
        "repne  scasb"

// macro for strlen() function
#define __I386_STRLEN               \
        __I386_STREND_IMPL          \
        "mov    eax, -2"            \
        "sub    eax, ecx"



И связываю эти макросы с параметрами для каждого компилятора по-своему:

#if defined(__WATCOMC__)
    // strlen function bindings for Watcom
    #pragma aux I386_STRLEN     =       \
            __I386_STRLEN               \
            parm caller [edi]           \
            value [eax]                 \
            modify [edi ecx]
#elif defined(__GNUC__)
    // strlen function bindings for GCC
    #define I386_STRLEN                 \
            __I386_STRLEN               \
            : "=a"(__result)            \
            : "D"(str)
#endif /* compiler detection */



После чего осталось объявить прототип функции:
inline_func(I386_STRLEN,    size_t,     __strlen(const char *str)                       )


Всё, теперь я могу использовать функцию __strlen, и она будет инлайниться во всех участках кода как для GCC, так и для Watcom. Замечательно, не правда ли?

(5 comments | Leave a comment)

Comments
 
From:trac3r
Date:April 8th, 2009 06:28 am (UTC)
(Link)
Давно пора :) Молодец!
[User Picture]
From:iijii
Date:April 8th, 2009 09:59 am (UTC)
(Link)
Вот :) мне бы твои заботы :)
[User Picture]
From:sadko4u
Date:April 8th, 2009 08:41 pm (UTC)
(Link)
В смысле?
[User Picture]
From:stalkerg
Date:April 9th, 2009 05:45 am (UTC)
(Link)
А мне кажется интеловский синтаксис - убог.
Я сколько пытался себя заставить на нём писать - так и не смог.
Порядок операндов добивает. *_*
[User Picture]
From:sadko4u
Date:April 10th, 2009 09:38 pm (UTC)
(Link)
На вкус и цвет :)
Мой родной проект. Powered by LiveJournal.com