このような状況で行う最善の方法は、試してみることです。プログラムの例を次に示します。
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)
これは、コードの正確な論理演算として非常に簡単に見られます。
- 初期化する
adad
- のアドレスを取る
adad
- そのアドレスに 2 を追加します
- 新しいアドレスを逆参照して 1 バイトをロードする
- 1 バイトを格納する
character
さまざまな最適化により出力が変更されます...何らかの理由で特定の動作/アドレス指定モードが本当に必要な場合は、アセンブリを自分で作成する必要がある場合があります。