0

printf()gcc はスタックに割り当てるメモリの量をどのように決定し、メインから (または任意の関数呼び出しを)削除しても %rsp を減らさないのはなぜですか?

1.コード サンプルをいじってみたところ、https: //godbolt.org/z/fQqkNEコードから削除すると6th line、gcc アセンブリ ビューアーsubq $48, %rspが削除されることに気付きました。メイン内から関数呼び出しを行わないと、デクリメントされませんが、データはオフセットに基づいて割り当てられます。スタックが成長したときにのみ変化すると思いました。私の理論は、他の関数呼び出しを行わないため、他の存在しない関数のスタックを保持する必要がないことを知っているというものです。しかし、データが保存されているので、まだ成長するべきではありませんか?printf()Cline 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 構文を使用しています。オンラインチュートリアルを見つけるのがずっと難しくなるので、これは奇妙です.

4

0 に答える 0