Как разделить два 64-разрядных числа на Ядро Linux?

Некоторый код, который окружает подразделение для демонстрации (синтаксис C):

#define SINT64 long long int
#define SINT32 long int

SINT64 divRound(SINT64 dividend, SINT64 divisor)
{
  SINT32 quotient1 = dividend / divisor;

  SINT32 modResult = dividend % divisor;
  SINT32 multResult = modResult * 2;
  SINT32 quotient2 = multResult / divisor;

  SINT64 result = quotient1 + quotient2;

  return ( result );
}

Теперь, если бы это было Пространство пользователя, то мы, вероятно, даже не заметили бы, что наш компилятор генерирует код для тех операторов (например, divdi3 () для подразделения). Возможности, мы связываемся с 'libgcc', даже не зная это. Проблема состоит в том, что пространство Ядра отличается (например, никакой libgcc). Что сделать?

Google проверки некоторое время, заметьте, что в значительной степени все обращаются к неподписанному варианту:

#define UINT64 long long int
#define UINT32 long int

UINT64 divRound(UINT64 dividend, UINT64 divisor)
{
  UINT32 quotient1 = dividend / divisor;

  UINT32 modResult = dividend % divisor;
  UINT32 multResult = modResult * 2;
  UINT32 quotient2 = multResult / divisor;

  UINT64 result = quotient1 + quotient2;

  return ( result );
}

Я знаю, как зафиксировать этого: Переопределите udivdi3 () и umoddi3 () с _do_div () _ от asm/div64.h. Сделанный правильно? Неправильно. Подписанный не то же, поскольку неподписанный, sdivdi3 () _ просто не называет udivdi3 (), они - отдельные функции по причине.

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

Спасибо, Чад

7
задан 30 August 2008 в 00:06
поделиться

4 ответа

Вот мое действительно наивное решение. Ваш пробег может варьироваться.

Сохраните знаковый бит, который является sign(dividend) ^ sign(divisor). (Или *, или /, если Вы храните свой знак как 1 и-1, в противоположность лжи и верные. В основном, отрицательный, если или каждый отрицателен, положителен, если ни один или оба не отрицательны.)

Затем вызовите неподписанную функцию подразделения на абсолютных значениях обоих. Затем прикрепите знак назад на результат.

P.S. Это на самом деле как __divdi3 реализован в libgcc2.c (от GCC 4.2.3, версия это установлено в моей системе Ubuntu). Я просто проверил.:-)

4
ответ дан 7 December 2019 в 05:35
поделиться

Эта функциональность представлена в/linux/lib/div64.c уже в ядре v2.6.22.

4
ответ дан 7 December 2019 в 05:35
поделиться

ldiv ?

Править: перечитайте заголовок, таким образом, Вы могли бы хотеть проигнорировать это. Или не, в зависимости от того, если это имеет соответствующую версию небиблиотеки.

0
ответ дан 7 December 2019 в 05:35
поделиться

Я не думаю (по крайней мере, не может найти способ сделать), работа ответа Chris в этом случае, потому что do_div () на самом деле изменяет оперативный дивиденд. Получение абсолютного значения подразумевает временную переменную, значение которой изменит способ, которым я требую, но не могу быть передан из моего __ divdi3 () переопределение.

Я не вижу путь вокруг подписи параметра значением __ divdi3 () в этой точке кроме подражать технике, используемой do_div ().

Могло бы казаться, что я наклоняюсь назад здесь и должен просто придумать алгоритм, чтобы сделать 64-bit/32-bit подразделение, в котором я на самом деле нуждаюсь. Добавленная сложность здесь, хотя то, что я имею набор цифрового кода с помощью '/' оператор и должен был бы пройти тот код и заменить каждый '/' моими вызовами функции.

Я становлюсь достаточно отчаянным, чтобы сделать просто это все же.

Спасибо за любое продолжение, Чад

0
ответ дан 7 December 2019 в 05:35
поделиться
Другие вопросы по тегам:

Похожие вопросы: