printf()
gcc はスタックに割り当てるメモリの量をどのように決定し、メインから (または任意の関数呼び出しを)削除しても %rsp を減らさないのはなぜですか?
1.コード サンプルをいじってみたところ、https: //godbolt.org/z/fQqkNEのコードから削除すると6th line
、gcc アセンブリ ビューアーsubq $48, %rsp
が削除されることに気付きました。メイン内から関数呼び出しを行わないと、デクリメントされませんが、データはオフセットに基づいて割り当てられます。スタックが成長したときにのみ変化すると思いました。私の理論は、他の関数呼び出しを行わないため、他の存在しない関数のスタックを保持する必要がないことを知っているというものです。しかし、データが保存されているので、まだ成長するべきではありませんか?printf()
C
line 22
%rsp
%rbp
%rsp
%rsp
2. my に変数を追加するとrect struct
、追加されたデータ型のサイズよりも大きなステップでメモリが割り当てられる場合があることにも気付きました。スタックに割り当てるメモリの量を決定するときに従う規則は何ですか?
3.アセンブリ コードを入力として受け取り、スタックのイメージを描画して、実行の任意の時点でのすべてのレジスタの状態を教えてくれるオンライン ツールはありますか? Godbolt.org は非常に優れたツールです。これら 2 つの追加機能があればいいのにと思います。
Godbolt へのリンクが将来機能しなくなった場合に備えて、以下のコードを貼り付けます。
#include <stdio.h>
#include <stdint.h>
struct rect {
int a;
int b;
int* c;
int d[2];
uint8_t f;
};
int main() {
int arr[2] = {2, 3};
struct rect Rect;
Rect.a = 10;
Rect.b = 20;
Rect.c = arr;
Rect.d[0] = Rect.a;
Rect.d[1] = Rect.b;
Rect.f =255;
printf("%d and %d", Rect.a, Rect.b);
return 0;
}
.LC0:
.string "%d and %d"
main:
pushq %rbp
movq %rsp, %rbp
subq $48, %rsp
movl $2, -8(%rbp)
movl $3, -4(%rbp)
movl $10, -48(%rbp)
movl $20, -44(%rbp)
leaq -8(%rbp), %rax
movq %rax, -40(%rbp)
movl -48(%rbp), %eax
movl %eax, -32(%rbp)
movl -44(%rbp), %eax
movl %eax, -28(%rbp)
movb $-1, -24(%rbp)
movl -44(%rbp), %edx
movl -48(%rbp), %eax
movl %eax, %esi
movl $.LC0, %edi
movl $0, %eax
call printf
movl $0, %eax
leave
ret
PS: 私がフォローしている本では、x86 を教えるために AT&T 構文を使用しています。オンラインチュートリアルを見つけるのがずっと難しくなるので、これは奇妙です.