9
(gdb) disas foo
Dump of assembler code for function foo:
0x00000000004004a8 <foo+0>: push   %rbp
0x00000000004004a9 <foo+1>: mov    %rsp,%rbp
0x00000000004004ac <foo+4>: mov    0x13c(%rip),%eax        # 0x4005ee <__dso_handle+30>
0x00000000004004b2 <foo+10>:    mov    %eax,-0x10(%rbp)
0x00000000004004b5 <foo+13>:    lea    -0x10(%rbp),%rax
0x00000000004004b9 <foo+17>:    add    $0x18,%rax
0x00000000004004bd <foo+21>:    mov    %rax,%rdx
0x00000000004004c0 <foo+24>:    mov    $0x400498,%eax
0x00000000004004c5 <foo+29>:    mov    %eax,(%rdx)
0x00000000004004c7 <foo+31>:    leaveq 
0x00000000004004c8 <foo+32>:    retq   
(gdb) l foo
8   void foo() {
9       char overme[4] = "WOW";
10      *(int*)(overme+24) = (int)bad;
11  }

なぜ8バイトだけではないのですか?

4

2 に答える 2

15

gcc は、このスペースを変数に「割り当て」ていません。代わりに、x86_64 abi では、呼び出し先がベクトル化された SSE 数学を使用する場合に備えて、スタック ポインターが関数呼び出しで常に 16 バイト アラインされている必要があります。これは本当にばかげた無駄の多い要件です (呼び出し先は、必要に応じてアライメントを確保する必要があります) が、それが標準であり、gcc は標準に従っています。-mpreferred-stack-boundary=3(8 バイト アラインメント、64 ビットの最小値) で修正できます。

于 2011-04-04T14:43:29.780 に答える
1

これは 16 バイトではなく 8 バイトです。LEA 命令はアラインメントに関連するものを何も表示しません。-0x10 は RBP レジスタの値に適用される単なるオフセットです。おそらく、小さなローカル配列のアドレスを生成するためです。コード ジェネレーターが SIMD 命令を使用する場合、16 が関連する可能性があります。2行の質問にはどれも表示されません。

于 2011-04-04T11:59:47.013 に答える