2

リンカ コマンド スクリプトで定義されたリンカ シンボル (__BASE_ADDR と呼びましょう) があります。これには、使用する必要があるロングワードのに​​ロングワードのアドレスが含まれています (たとえば、アドレス 0x0000000C でロングワードをチェックする必要があり、__BASE_ADDR は 0x00000010 に等しい) )。そのため、コードでは __BASE_ADDR を使用し、そこから 4 を引いて 0x0000000C にアクセスしようとしています。

私のリンカ マップ出力は、__BASE_ADDR の値が 0x00000010 であることを正しく示しています。ただし、次の C コードを使用してその場所にアクセスしようとすると、機能しません。

extern unsigned char *__BASE_ADDR;

void someFunc( void )
{
    unsigned long Val = *((unsigned long *) (__BASE_ADDR - 4));

    /* Use Val for some comparison...*/
    /* ... */
}

Val が間違った値に設定されます。起こっているように見えるのは、__BASE_ADDR にあるロングワードがアドレスとして取得され、4 が減算され、結果のアドレスの内容が Val に入れられるということです。

しかし、次のようにすると、問題なく動作し、Val はアドレス 0x0000000C にあるものに正しく設定されます。

extern unsigned char __BASE_ADDR[];

void someFunc( void )
{
    unsigned long Val = *((unsigned long *) (__BASE_ADDR - 4));

    /* Use Val for some comparison...*/
    /* ... */
}

誰でもこれに光を当てることができますか?リンカー シンボルのコンテンツにアクセスできない (技術的にはコンテンツがない) 理由は理解できますが、リンカー シンボルをポインターとしてアクセスする場合と配列としてアクセスする場合に違いがあるのはなぜですか?

ありがとう。

4

1 に答える 1

3

(たとえば、アドレスのロングワードをチェックする必要があり、0x0000000C__BASE_ADDR等しい0x00000010)

症状は0x00000010、 の__BASE_ADDRはなく、アドレスであると言っています。

そう

unsigned long Val = *((unsigned long *) (__BASE_ADDR - 4));

は実際に の値を読み取り0x00000010( の値を取得)、そこから 4 を引き、その結果をに格納する__BASE_ADDRのアドレスとして解釈します。unsigned longval

extern unsigned char __BASE_ADDR[];

配列__BASEADDRのアドレスは配列の最初の要素のアドレスと同じなので、その場合、

unsigned long Val = *((unsigned long *) (__BASE_ADDR - 4));
  • 配列名__BASE_ADDRをその最初の要素へのポインターに変換し、結果として得られるアドレスは__BASE_ADDR(ちょうど異なる型の)のアドレス0x00000010です。
  • それから 4 が引かunsigned char*れ、アドレスが得られます0x0000000C
  • 次に、そのアドレスが にキャストされunsigned long*、逆参照され、そこにある値が に格納されvalます。

(最後のポイントは未定義の動作を引き起こす可能性が非常に高いです、固定アドレスを扱う場合は、それが機能することがわかっている状況にある可能性があります。)

于 2013-04-22T15:29:27.993 に答える