Страниц: [1] 2
  Печать  
Автор Тема: __receivemx() / __sendmx() / __replymx()  (Прочитано 10475 раз)
@nger
Гость
« : Февраля 15, 2010, 04:21:25 pm »

Кто-нибудь пытался сабжевые функции в gcc под 4-ой использовать?
Записан
AG
QOR.Moderator
*****
Offline Offline

Сообщений: 872



Просмотр профиля WWW
« Ответ #1 : Февраля 15, 2010, 05:02:05 pm »

К чему такой вопрос, коллега? Если сказал "А", то и говорите "Б". Не работает что-то?

ЗЫЖ Я бы не использовал gcc (egcs) под четверкой для чего-то серьезного вообще - слишком топорный порт. Никто не может дать гарантии, что оно работать будет. Хотя biew для QNX4 я собирал именно с его помощью...
Записан

@nger
Гость
« Ответ #2 : Февраля 15, 2010, 05:11:23 pm »

Боюсь, пока, с gcc я связан достаточно тесно, т.к. watcom не умеет (по крайней мере я этого не увидел) X-овые либы кушать =)

Суть проблемы сводится к следующему: данные функции объявлены и определены в хедере и написаны на ин-лайн ассемблере watcom. В свою очередь линкер gcc не находит их.

Я пытался уже переписать в соответствии с ин-лайновым синтаксисом асма gcc, но говорить об этом хотел бы в крайнем случае, т.к. с асмом по роду деятельности сталкиваюсь достаточно редко =) И результаты переноса функций меня, мягко говоря, удивили =)))

Т.о. может быть есть более грамотный способ.
« Последнее редактирование: Февраля 16, 2010, 11:42:52 am от @nger » Записан
oder
Гость
« Ответ #3 : Февраля 15, 2010, 07:34:23 pm »

Подумаешь, проблемы! Если функции небольшие, давайте и исходник и переделку - проверим!
Записан
@nger
Гость
« Ответ #4 : Февраля 16, 2010, 11:41:44 am »

Поскольку других альтернатив нет, прошу:

Код: (Watcom)
extern int __sendmx(
            int                   __pid,
            unsigned              __smsg_xparts,
            unsigned              __rmsg_xparts,
            const struct _mxfer_entry  *__smsg,
            const struct _mxfer_entry  *__rmsg );
#pragma aux __sendmx =                   \
    "mov al,00h"                         \
    "clc"                                \
    "int 0f2h"                           \
    "jnc l1"                             \
    "call __kererr"                      \
    "l1:"                                \
    __parm [edx] [ah] [ch] [ebx] [esi]   \
    __modify __exact [eax]               \
    __value [eax]                        \
    ;

Код: (GCC)
int __sendmx(
            int                   __pid,
            unsigned              __smsg_xparts,
            unsigned              __rmsg_xparts,
            const struct _mxfer_entry  *__smsg,
            const struct _mxfer_entry  *__rmsg ) {

    __asm__ __volatile__ (
        "shl $8, %%eax      \n"
        "shl $8, %%ecx      \n"
        "mov $0x00, %%al    \n"
        "clc                \n"
        "int $0x0f2         \n"
        : "=a" (__pid)
        : "d" (__pid), "a" (__rmsg_xparts), "c" (__rmsg_xparts), "b" (__smsg), "S" (__rmsg)
        : "%eax", "%ecx"
    );

    return __pid;

}

Получите, распишитесь.

Больше всего меня смущает то, что отправка сообщения в GCC происходит только если в EAX = 0x00 (т.е. если не передавать параметр __rmsg_xparts), в Watcom же отправка проходит нормально даже при EAX = 0x200. Если же исполняю представленный GCC-код (например в EAX = 0x200) отправка не происходит и возвращается значение 0xe.
« Последнее редактирование: Февраля 16, 2010, 11:45:23 am от @nger » Записан
oder
Гость
« Ответ #5 : Февраля 16, 2010, 03:55:19 pm »

Ну, я бы сделал это так

int __sendmx(
          int                   __pid,
          unsigned              __smsg_xparts,
          unsigned              __rmsg_xparts,
          const struct _mxfer_entry  *__smsg,
          const struct _mxfer_entry  *__rmsg ) {
   return ( {
      register int status;
      __asm__ (
        "mov %%al, %%ah    \n"
        "mov %%cl, %%ch    \n"
        "xor %%al, %%al    \n"
        "int $0x0f2        \n"
      "jnc no_error      \n"
      "call __kererr     \n"
   "no_error:             \n"

        : "=a" (status)
        : "d" (__pid), "a" (__rmsg_xparts), "c" (__rmsg_xparts), "b" (__smsg), "S" (__rmsg)
        : "eax", "ecx"
      );
      status
   } );
}

Хотя, принципиальных причин не работать и в Вашей реализации не вижу.
Разве что, покажите ещё дизассемблерный дамп скомпилированной GCC функции.
Записан
@nger
Гость
« Ответ #6 : Февраля 16, 2010, 05:18:47 pm »

Прошу:

GCC:


Watcom:
Записан
oder
Гость
« Ответ #7 : Февраля 16, 2010, 07:31:10 pm »

Ну вот, всё сразу стало очевидным.
       : "d" (__pid), "a" (__rmsg_xparts), "c" (__rmsg_xparts), "b" (__smsg), "S" (__rmsg)
Копи-пейст, однако.
Записан
@nger
Гость
« Ответ #8 : Февраля 16, 2010, 09:01:53 pm »

Ну вот, всё сразу стало очевидным.
       : "d" (__pid), "a" (__rmsg_xparts), "c" (__rmsg_xparts), "b" (__smsg), "S" (__rmsg)
Копи-пейст, однако.

Это не играет роли =)

При вызове оба параметра равны 2:
__sendmx( pid, 2, 2, mx, mx );
 Grin
« Последнее редактирование: Февраля 16, 2010, 09:05:39 pm от @nger » Записан
oder
Гость
« Ответ #9 : Февраля 16, 2010, 09:13:05 pm »

Скомпилируйте мой вариант.
Последний "mov +8[ebp], eax" - явно ни к чему. И это "ни к чему" возникает из того, что Вы переиспользовали входной параметр в качестве результата. А дальше текст функции Вы обрезали. Так что, посмотреть, правильно ли код возвращает результат я не могу.
Записан
oder
Гость
« Ответ #10 : Февраля 16, 2010, 09:19:08 pm »

Больше всего меня смущает то, что отправка сообщения в GCC происходит только если в EAX = 0x00 (т.е. если не передавать параметр __rmsg_xparts), в Watcom же отправка проходит нормально даже при EAX = 0x200. Если же исполняю представленный GCC-код (например в EAX = 0x200) отправка не происходит и возвращается значение 0xe.

И ещё, относительно 0xe...
#define EFAULT          14  /* Bad address                              */

Может, всё-таки, буфер кривой?
« Последнее редактирование: Февраля 16, 2010, 09:43:20 pm от oder » Записан
@nger
Гость
« Ответ #11 : Февраля 16, 2010, 11:46:54 pm »

Больше всего меня смущает то, что отправка сообщения в GCC происходит только если в EAX = 0x00 (т.е. если не передавать параметр __rmsg_xparts), в Watcom же отправка проходит нормально даже при EAX = 0x200. Если же исполняю представленный GCC-код (например в EAX = 0x200) отправка не происходит и возвращается значение 0xe.

И ещё, относительно 0xe...
#define EFAULT          14  /* Bad address                              */

Может, всё-таки, буфер кривой?

Сильно сомневаюсь, т.к. при записи в EAX 0x00 возвращается корректный результат и происходит передача сообщения (__receivemx реагирует на прием). Буфер же остается тем что и был до изменения EAX.

Скомпилируйте мой вариант.
Последний "mov +8[ebp], eax" - явно ни к чему. И это "ни к чему" возникает из того, что Вы переиспользовали входной параметр в качестве результата. А дальше текст функции Вы обрезали. Так что, посмотреть, правильно ли код возвращает результат я не могу.

mov +8[ebp], eax и есть возврат результата (ret отсутствует из-за оптимизации компилятора):
mov eax, +10[ebp]    <--->     "a" (__rmsg_xparts)
mov +8[ebp], eax      <--->     return __pid;

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

Хорошо, попробую запустить Ваш вариант в четверг.
Записан
oder
Гость
« Ответ #12 : Февраля 17, 2010, 12:01:08 am »

Ну так ah это количество отсылаемых частей. Если его обнулить, так ничего не отсылается и буфер __smsg игнорируется. А если ah = 2, то буфер __smsg проверяется и возвращается ошибка, что память в нём недоступна. А на прием, может, или буфер не проверяется или не приходит ничего - фиг её знает эту четвёрку.
Чудес не бывает! Если функция говорит EFAULT, значит - EFAULT.

P.S. И копи-пейст исправьте обязательно!
P.P.S. И, вообще, странно, зачем оно в [ebp+?] параметры раскладывает если функция инлайном скомпилирована. :-/
« Последнее редактирование: Февраля 17, 2010, 12:04:25 am от oder » Записан
@nger
Гость
« Ответ #13 : Февраля 17, 2010, 09:16:02 am »

Ну так ah это количество отсылаемых частей. Если его обнулить, так ничего не отсылается и буфер __smsg игнорируется. А если ah = 2, то буфер __smsg проверяется и возвращается ошибка, что память в нём недоступна. А на прием, может, или буфер не проверяется или не приходит ничего - фиг её знает эту четвёрку.
Чудес не бывает! Если функция говорит EFAULT, значит - EFAULT.

Скорее всего Вы правы, т.к. из wd становится очевидным, что выделение памяти в гцц коренным образом отличается от ваткома (хоть это и не должно играть роли в идеале). Правда, я полагал что если буфер отсутствует, то сообщение отправляться не должно =)

P.S. И копи-пейст исправьте обязательно!

Само собой =)

P.P.S. И, вообще, странно, зачем оно в [ebp+?] параметры раскладывает если функция инлайном скомпилирована. :-/

А хтоб его знал.
Записан
@nger
Гость
« Ответ #14 : Февраля 18, 2010, 12:15:29 pm »

Ну, я бы сделал это так

int __sendmx(
          int                   __pid,
          unsigned              __smsg_xparts,
          unsigned              __rmsg_xparts,
          const struct _mxfer_entry  *__smsg,
          const struct _mxfer_entry  *__rmsg ) {
   return ( {
      register int status;
      __asm__ (
        "mov %%al, %%ah    \n"
        "mov %%cl, %%ch    \n"
        "xor %%al, %%al    \n"
        "int $0x0f2        \n"
      "jnc no_error      \n"
      "call __kererr     \n"
   "no_error:             \n"

        : "=a" (status)
        : "d" (__pid), "a" (__smsg_xparts), "c" (__rmsg_xparts), "b" (__smsg), "S" (__rmsg)
        : "eax", "ecx"
      );
      status
   } );
}

Эффект тот же самый.

В итоге, в gcc данный код не работает.
Записан
Страниц: [1] 2
  Печать  
 
Перейти в: