2008-08-29 3 views
5

кода, который округляет подразделение, чтобы продемонстрировать (C-синтаксис):Как разделить два 64-разрядных номера в ядре Linux?

#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). Что делать?

Crawl 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); 
} 

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

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

Спасибо, Чад

ответ

0

ldiv?

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

4

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

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

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

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

0

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

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

Может показаться, что я наклоняюсь назад здесь и должен просто придумать алгоритм для выполнения 64-битного/32-битного деления, который мне действительно нужен. Однако добавленное усложнение состоит в том, что у меня есть куча числового кода с использованием оператора «/», и вам нужно будет пройти через этот код и заменить каждый «/» на мои вызовы функций.

Я получаю отчаяние, чтобы сделать это.

Спасибо за любую последующую деятельность, Чад