6


0

デモンストレーションのために切り上げたコード(C構文):

#define SINT64 long long int #define SINT32 long int

SINT64 divRound(SINT64被除数、SINT64除数){SINT32商1 =被除数/除数;

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

SINT64 result = quotient1 quotient2;

戻り値(結果) }

さて、これがユーザー空間であれば、私たちのコンパイラがそれらの演算子のためのコードを生成していることに気付くことさえおそらくないでしょう。 除算の場合は_divdi3()_。 知らないうちに 'libgcc’とリンクしているのかもしれません。 問題はカーネル空間が異なることです(例: いいえlibgcc)。 何をすべきか?

Googleをしばらくクロールします。ほとんどの人が署名なしの亜種に対処しています。

#define UINT64 long long int #define UINT32 long int

UINT64 divRound(UINT64の被除数、UINT64の除数){UINT32の商1 =被除数/除数。

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

UINT64 result = quotient1 quotient2;

戻り値(結果) }

私はこれを修正する方法を知っています:_asm / div64.h_から_do_div()_で_udivdi3()_と_umoddi3()_を上書きします。 やった? 違う。 Signedはunsignedと同じではありません。sdivdi3()_は単に_udivdi3()_を呼び出すのではなく、理由により別々の関数です。

あなたはこの問題を解決しましたか? あなたが私を助けてくれる図書館を知っていますか? 私は本当に立ち往生しているので、あなたがここで見るかもしれないものは何でも私は今は駄目だと本当に役立つでしょう。

ありがとう、チャド

4 Answer


4


これが私の本当に素朴な解決策です。 あなたのマイレージは異なる場合があります。

符号ビットを保持してください。これは sign(dividend)^ sign(divisor)`です。 (または、falseやtrueではなく、符号を1と-1として格納している場合は、 `*、または /。 基本的に、どちらか一方が負の場合は負、どれもまたは両方が負の場合は正です。)

次に、両方の絶対値で符号なし除算関数を呼び出します。 それから結果にサインを戻してください。

P.S. それが実際に __divdi3`が libgcc2.c`(GCC 4.2.3以降、私のUbuntuシステムにインストールされているバージョン)に実装されている方法です。 私はちょうど調べました。 :-)


4


この機能は、カーネルv2.6.22と同じくらい早くhttp://lxr.linux.no/linux v2.6.22 / lib / div64.c [/linux/lib/div64.c]に導入されています。


0


「ldiv」?

編集:タイトルを読み直すので、これは無視してもかまいません。 そうでない場合は、適切な非ライブラリバージョンがあるかどうかによって異なります。


0


私は考えていません(少なくとも作る方法を見つけることができない)https://stackoverflow.com/questions/35463/how-to-divide-two-64-bit-numbers-in-linux-kernel#35472 * do_div() は実際にはその場で配当を変更するので、[Chris 'answer]このケースで動作します。 絶対値を取得することは一時的な変数を意味しますが、その値は要求される方法を変更しますが、 _ divdi3()_ *オーバーライドから渡すことはできません。

この時点では、* _ do_div()_ で使用されている手法を模倣すること以外は、 _ divv3() *の値によるパラメータシグネチャを回避する方法はありません。

私はここで逆向きに曲がっているように見え、実際に必要な64ビット/ 32ビット除算を実行するためのアルゴリズムを思いつくべきです。 ただし、ここでさらに複雑になるのは、 '/'演算子を使用した一連の数値コードがあるため、そのコードを調べてすべての '/'を自分の関数呼び出しに置き換える必要があることです。

私はそれをするのに十分に必死になっています。

フォローアップをありがとう、チャド