他の人は、この振る舞いの未定義性を十分にカバーしています。あなたの特定の質問は、分解を理解することについてであるように見えました。これはやや冗長ですが、うまくいけば役立つウォークスルーです。
最初の指示:mov rax, [rbp - 16]
RBPは「ベースポインタレジスタ」です。これは、現在のスタックフレームのメモリにアドレスを保持します。コメント投稿者が指摘してrbp - 16
いるように、現在のスタックフレーム内の。の場所ですp
。8バイトのポインタになります。そのアドレスのint *q;
直後に別のローカル変数を宣言した場合、おそらく。になります。この場合、RAXは汎用レジスタです。これにより、8バイトのポインタがスタック上の位置からRAXにコピーされます。他の人が指摘しているように、初期化していないので、atの値は、そのメモリを最後に使用したことによってメモリに残されたもの、または完全にランダムなものです。角括弧括弧は、オペランドがポインタであり、アドレスのメモリの内容を示します。p
rbp - 24
rbp - 16
p
rbp - 16
rbp - 16
rbp - 16
式のリテラル結果ではなく、コピーする必要がありますrbp - 16
。rbp - 16
式はタイプを持つと考えることができますint**
。
2番目の指示:mov qword [rax], 1
QWORDは「クワッドワード」の略です。歴史的に、1バイトは1バイト、「ワード」は2バイト、「ロング」または「dword」(「ダブルワード」の場合)は4バイト、そして当然のことながら「クワッドワード」は8バイトです。この命令は、リテラル1(8バイト形式に拡張)をRAXが指す場所にコピーします。角括弧括弧は、オペランドRAXがポインターであり、リテラルがオペランドが指す場所にコピーされることを示します。命令がmov qword rax, 1
、リテラル1(8バイト形式)をRAXにコピーする場合。
他の人が言っているように、そのポインタはガベージ(メモリ内にたまたまあったもの)であるため、これがクラッシュする可能性は十分にあります(ただし保証はされません)。