0

2つの整数変数と文字変数があるとします。

int adad=12345;
char character;

整数変数の長さが3バイト以上であるプラットフォームについて説明していると仮定すると、この整数の3番目のバイトにアクセスして文字変数に入れたいと思います。つまり、次のように記述します。これ:

character=*((char *)(&adad)+2);

そのコード行と、私がコンパイラまたはアセンブリの専門家ではないという事実を考慮すると、アセンブリのアドレッシングモードについて少し知っていて、3番目のバイトのアドレスについて疑問に思っています(または、オフセットと言った方がいいと思います) 3番目のバイト)ここでは、そのコード行自体によって生成された命令内にありますか、それともアドレス(またはオフセット)がそれらの命令内にある別の変数にありますか?

4

2 に答える 2

3

このような状況で行う最善の方法は、試してみることです。プログラムの例を次に示します。

int main(int argc, char **argv)
{
  int adad=12345;
  volatile char character;

  character=*((char *)(&adad)+2);

  return 0;
}

を追加しvolatileて、割り当て行が完全に最適化されないようにしました。さて、これがコンパイラーが思いついたものです(-Oz私のMacの場合):

_main:
    pushq   %rbp
    movq    %rsp,%rbp
    movl    $0x00003039,0xf8(%rbp)
    movb    0xfa(%rbp),%al
    movb    %al,0xff(%rbp)
    xorl    %eax,%eax
    leave
    ret

気にするのは次の 3 行だけです。

    movl    $0x00003039,0xf8(%rbp)
    movb    0xfa(%rbp),%al
    movb    %al,0xff(%rbp)

movl初期化ですadad。次に、ご覧のとおり、 の 3 番目のバイトを読み取り、それadadをメモリに格納します (volatileはその格納を強制しています)。

良い質問だと思いますが、どのアセンブリが生成されるかがなぜ重要なのですか? たとえば、最適化フラグを に変更するだけ-O0で、コードの興味深い部分のアセンブリ出力は次のようになります。

    movl    $0x00003039,0xf8(%rbp)
    leaq    0xf8(%rbp),%rax
    addq    $0x02,%rax
    movzbl  (%rax),%eax
    movb    %al,0xff(%rbp)

これは、コードの正確な論理演算として非常に簡単に見られます。

  1. 初期化するadad
  2. のアドレスを取るadad
  3. そのアドレスに 2 を追加します
  4. 新しいアドレスを逆参照して 1 バイトをロードする
  5. 1 バイトを格納するcharacter

さまざまな最適化により出力が変更されます...何らかの理由で特定の動作/アドレス指定モードが本当に必要な場合は、アセンブリを自分で作成する必要がある場合があります。

于 2010-08-07T15:02:06.410 に答える
2

コンパイラと基礎となる CPU アーキテクチャについて何も知らなければ、決定的な答えは得られません。たとえば、すべての CPU アーキテクチャがメモリ内のすべての任意のバイトのアドレス指定を許可しているわけではありません (ただし、現在一般的なものはすべて許可されていると思います): バイト アドレスではなくワード アドレスの CPU では、コンパイラが生成するものは必然的に次のようになります。ワード全体を何らかのレジスターにロードしadad(問題の変数がスタック [1] にある場合は、おそらくベース・ポインター・レジスターからのオフセットによって)、その後にシフトとマスキングを行って、対象のバイトを分離します。

[1] 話している CPU アーキテクチャと、コンパイラがそれをどのように使用するかを知らなければ、「ベース レジスタからの固定オフセットでワードをロードする」ことが、命令 (希望するかもしれませんが、多くの一般的なアーキテクチャは間違いなくサポートしています;-) または補助レジスタで別のアドレス演算が必要です。

IOW、それが良いアイデアであるかどうかにかかわらず、他のレジスタまたは他のレジスタまたは定数によって定義されたメモリアドレスから以外のレジスタをロード/ストアできないCPUアーキテクチャを定義することは間違いなく可能であり、そのようなアーキテクチャがいくつか存在します(すべてではないかもしれませんが)現時点では人気があります;-)。

于 2010-08-07T15:01:33.210 に答える