2

友達にこの質問をされたのですが、関数の意味がわかりません.上のメモのようなものかもしれませんが、関数が/* sign-extend to 32 bits */「32ビットに符号拡張する」という役割をどのように実現しているかを詳しく知りたいです.

Linux カーネルからの関数。すべてthx。

@unwind が言ったように、関数の完全な定義は次のとおりです。

/* Convert a prel31 symbol to an absolute address */
#define prel31_to_addr(ptr)                         \
({                                                  \
    /* sign-extend to 32 bits */                    \
    long offset = (((long)*(ptr)) << 1) >> 1;       \
    (unsigned long)(ptr) + offset;                  \
})

そしてそれは関数で使用されます:

int __init unwind_init(void)
{
    struct unwind_idx *idx;

    /* Convert the symbol addresses to absolute values */
    for (idx = __start_unwind_idx; idx < __stop_unwind_idx; idx++)
        idx->addr = prel31_to_addr(&idx->addr);

    pr_debug("unwind: ARM stack unwinding initialised\n");

    return 0;
}
4

2 に答える 2

3

例として、ここで呼び出されている場所を見てください。

else if ((idx->insn & 0x80000000) == 0)
    /* prel31 to the unwind table */
    ctrl.insn = (unsigned long *)prel31_to_addr(&idx->insn);

ptrそのため、トップ (31 番目) ビットが設定されていない値への逆参照が渡されたことがわかります。prel31名と結びついている場合、その並べ替えは、この値で (下位) 31 ビットのみが使用されることを意味します。

符号付き 31 ビット値を符号付き 32 ビット値に変換するには、上位ビットを修正する必要があります。有効なビットはまだ 31 ビットしかありませんが、負の値には上位ビットを設定する必要があります。既存の 31 ビット値の符号と一致するように最上位ビットを設定することが符号拡張です。

1 ビット左シフトすると、既存の最上位ビットが破棄されます。再び右にシフトすると、符号を保持するために最上位ビットが埋められます (したがって、元の 31 ビット値が負の場合は 1 になり、そうでない場合は 0 になります)。

例えば。31 ビット値 (-1) として解釈される場合0x7FFFFFFFですが、32 ビット値 (2,147,483,647) として解釈される場合は正です。31 ビット バージョンと同じ意味を持つ 32 ビット エンコーディングを取得するには、次のようにします。

  • 未使用の最上位ビットを破棄するために左にシフトします: 0x7FFFFFFF << 1 => 0xFFFFFFFE(現在は負の 32 ビット値です)
  • 再度右にシフトして、下位 31 ビットの元のパターンを復元しますが、符号に応じて上位ビットを埋めます。0xFFFFFFFE >> 1 => 0xFFFFFFFF = -1

この (符号拡張) 動作はプラットフォーム固有であることに注意してください。ただし、このコードはすべてそうです。なぜこれらすべてを実行することが理にかなっているのかを理解するには (単に符号拡張の意味やビット パターンに何が起こるかではなく)、使用されているアドレッシング スキームを調査する必要があります。

于 2012-09-25T08:49:28.373 に答える
2

私はこれがそれがすることだと思います:

*ptrビット 30 (MSB より 1 少ない) に符号ビットを持つ符号付き 31 ビット値が含まれているため、左にシフトすると符号ビットはビット 31 (MSB) になり、右にシフトして戻すと符号ビット「拡張」され、ビット 30 とビット 31 に表示されます。

つまり、ビット 30 をビット 31 にコピーします。

于 2012-09-25T08:48:55.913 に答える