2

スタックに長さ8のchar配列にスペースを割り当てるdemo.cという単純なプログラムがあります

#include<stdio.h>


main()
{
        char buffer[8];

        return 0;
}

8 文字のスタックから 8 バイトが割り当てられると思っていましたが、gdb でこれを確認すると、スタックから 10 バイトが差し引かれています。

Ubuntu 32 ビット マシンで次のコマンドを使用してプログラムをコンパイルします。

$ gcc -ggdb -o デモ demo.c

次に、プログラムを次のように分析します。

$ gdb デモ

$ メインを逆アセンブル

(gdb) disassemble main
Dump of assembler code for function main:
   0x08048404 <+0>: push   %ebp
   0x08048405 <+1>: mov    %esp,%ebp
   0x08048407 <+3>: and    $0xfffffff0,%esp
   0x0804840a <+6>: sub    $0x10,%esp
   0x0804840d <+9>: mov    %gs:0x14,%eax
   0x08048413 <+15>:    mov    %eax,0xc(%esp)
   0x08048417 <+19>:    xor    %eax,%eax
   0x08048419 <+21>:    mov    $0x0,%eax
   0x0804841e <+26>:    mov    0xc(%esp),%edx
   0x08048422 <+30>:    xor    %gs:0x14,%edx
   0x08048429 <+37>:    je     0x8048430 <main+44>
   0x0804842b <+39>:    call   0x8048340 <__stack_chk_fail@plt>
   0x08048430 <+44>:    leave  
   0x08048431 <+45>:    ret    
End of assembler dump.

0x0804840a <+6>: sub $0x10,%esp は、スタックから 10 バイトが割り当てられていると言っていますよね?

8 バイトではなく 10 バイトが割り当てられているのはなぜですか?

4

4 に答える 4

5

いいえ、0x1016 進数、つまり 10 16であることを意味します。これは、10 進数で 16 10バイトです。

おそらく、スタックのアライメント要件が原因です。

于 2012-10-25T15:42:00.920 に答える
3

sub $0x10, %esp0xは16 進数表記であるため、10 ではなく、スタックに 16 バイトあると言っています。

スタックのスペースの量は、コンパイラに完全に依存します。この場合、アラインメントが 16 バイトであり、8 を要求したため、16 に増加するアラインメントの問題に最も似ています。

17 バイトを要求した場合、17 バイトではsub $0x20, %espなく 32 バイトである可能性が高くなります。

于 2012-10-25T15:52:04.873 に答える
3

定数 $0x10 は 16 進数であり、これは 16 バイトに等しいことに注意してください。マシンコードを見てください:

0x08048404 <+0>: push   %ebp
0x08048405 <+1>: mov    %esp,%ebp
0x08048407 <+3>: and    $0xfffffff0,%esp
0x0804840a <+6>: sub    $0x10,%esp
...
0x08048430 <+44>:    leave  
0x08048431 <+45>:    ret 

esp から 16 を減算する前にわかるように、最初に esp が 16 バイトにアラインされたアドレスを指すようにします (and $0xfffffff0,%esp命令を見てください)。コンパイラはアラインメントを尊重しようとするので、16バイトも予約するだけです。とにかく、8 バイトは 16 バイトにうまく収まるので問題ありません。

于 2012-10-25T15:51:28.097 に答える