3

次のようにメモリを埋めます。

char buf[8] = { 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88};

そして、最初の 5 バイトと出力結果に順番に unsigned long ポインターを置きます。

char *c_ptr;
unsigned long *u_ptr;

c_ptr = buf;
for (int i=0;i<5;i++)
{
    u_ptr = (unsigned long *)c_ptr;
    printf("%X\n",*u_ptr);
    c_ptr++;
}

x64 プラットフォームでこのコードを実行すると、期待どおりの結果が得られます。

44332211
55443322
66554433
77665544
88776655

しかし、ARM プラットフォームで同じコードを実行すると、次のようになります。

44332211
11443322
22114433
33221144
88776655

つまり、4 バイトごとにバインドされ、この境界内の 4 バイトのみを逆参照します。

pointer_value%4 != 0だから私は、この動作(いつ)が間違っているのか、それとも実装固有のものなのかを尋ねたいと思いますか?

UPD:エンディアンについては知っていましたが、これが正しいことを知りたいです。

11443322

それ以外の

55443322

つまり、たとえばポインターがある場合、 の代わりに、、および よりも0x10000001 アドレスを持つバイトから unsigned long を作成します。0x100000010x100000020x100000030x100000000x10000005

4

4 に答える 4

3

メモリの配置を疑った後、私は簡単なグーグルをしました=)

http://awayitworks.blogspot.co.nz/2010/02/arm-memory-alignment.html

その記事では次のように述べられています。

ARMv4 アーキテクチャまでは、コンテンツをフェッチするために指定されたアドレスはメモリにアラインされていると想定されていました... 32 ビットのデータ フェッチでは、アドレスが 32 ビットにアラインされている必要があります。正しく推測されているように、問題は 32 ビットおよび 16 ビットのデータ フェッチのみです。ARM は、データ フェッチが 32 ビットの場合はアドレスの下位 2 ビットを無視し、データ フェッチが 16 ビットの場合は下位 1 ビットを無視します。したがって、アドレスが適切にアラインされていない場合、データ フェッチはエラーになります。

最後の文に注意してください =)

x86 で期待した動作が必要な場合は、char から整数を明示的に作成する必要があります(リトルエンディアンを想定)。

// Endian-specific
inline unsigned long ulong_at( const char *p ) {
    return ((unsigned long)p[0])
         | (((unsigned long)p[1]) << 8)
         | (((unsigned long)p[2]) << 16)
         | (((unsigned long)p[3]) << 24);
}

多分:

// Architecture-specific
inline unsigned long ulong_at( const char *p ) {
    unsigned long val;
    char *v = (char*)&val;
    v[0] = p[0];
    v[1] = p[1];
    v[2] = p[2];
    v[3] = p[3];
    return val;
}
于 2012-09-16T22:33:47.230 に答える
2

メモリから 4 バイト ワードをフェッチする場合、アドレスは 4 の倍数である必要があります。

一般に、アクセスの不整合は、どのアーキテクチャでも悪い考えです。SEGFAULT をスローするものもあれば、フォールトを透過的に処理し、非常にゆっくりと、目的の値を含む 2 つのワードをフェッチしてそれらをつなぎ合わせることで正しい値を合成するものもあります。(私は専門家ではありませんが) ARM は、ポインターが占有する 4 バイトのスロットをフェッチし、レジスターの LSB がポインターと一致するように結果をローテーションしているようです。

于 2012-09-16T22:34:39.660 に答える
1

エンディアンはこの動作を説明しません。ARM プロセッサは、4 バイト境界にアラインされていない 4 バイト メモリ アクセスを許可していないようであり、出力は、プロセッサがメモリを読み取ったことを示しています。 4 バイト境界。メモリ アラインメントの詳細については、このウィキペディアの記事を参照してください。

実際、一部のアーキテクチャでは、この種のアライメントされていないメモリ アクセスを実行しようとすると、バス エラーが発生する場合があります。

于 2012-09-16T22:27:20.150 に答える
1

問題は、ハードウェアによっては未定義である可能性がある、アライメントされていないポインターを逆参照していることです。long*多くのアーキテクチャでは、aが 32 ビットのメモリにアラインされる、つまり 4 で割り切れると想定しています。そうでない場合、結果は未定義です。

一般に、C は、あるポインター型を別の型にキャストしたときに何が起こるかを保証しません。

于 2012-09-16T22:35:54.083 に答える