0

2つの質問があります。

最初の質問。次のコードが実際にMacで動作するのはなぜですか(gccでコンパイル)?

int main()
{
    int *p;
    *p = 1;
    return 0;
}

行を分解すると'*p = 1;' になります

mov rax, [rbp - 16]
mov qword [rax], 1

2番目の質問。[rbp-16]には何がありますか?

質問をしている間、私はオペランド[rbp-16]を[rbp + 16]と解釈しましたが、これは明らかに意味がありません。私は疲れていた...

私の質問に答えてくれてありがとう。

4

3 に答える 3

3

コードの動作は未定義です。これが意味することは、それが何でもすることが許されるということです。クラッシュする必要はありません。

プログラムの起動時に、以前に実行されmain()、同じスタックを使用するコードがあります。ボックスで発生する可能性が高いのは、スタックの領域がp、有効なポインタをそこに保持している別の関数によって以前に使用されていたことです。あなたmain()は誤ってそのポインタに遭遇し、それを逆参照し、他の誰かの記憶を破壊しています。

gccOSXを使用してコードをコンパイルして実行しようとしましたが、クラッシュしました。

于 2013-02-12T10:27:47.870 に答える
1

私が覚えているように、Cの変数は、以前のユーザーがスタックに残した値によって初期化されます-値を明示的に指定しなかった場合。したがって、この値は完全にランダムであり、コードはランダムメモリ領域の値を変更しただけです。nullポインタを取得すると、プログラムは失敗します。

于 2013-02-12T10:27:37.700 に答える
0

他の人は、この振る舞いの未定義性を十分にカバーしています。あなたの特定の質問は、分解を理解することについてであるように見えました。これはやや冗長ですが、うまくいけば役立つウォークスルーです。

最初の指示:mov rax, [rbp - 16]

RBPは「ベースポインタレジスタ」です。これは、現在のスタックフレームのメモリにアドレスを保持します。コメント投稿者が指摘してrbp - 16いるように、現在のスタックフレーム内の。の場所ですp。8バイトのポインタになります。そのアドレスのint *q;直後に別のローカル変数を宣言した場合、おそらく。になります。この場合、RAXは汎用レジスタです。これにより、8バイトのポインタがスタック上の位置からRAXにコピーされます。他の人が指摘しているように、初期化していないので、atの値は、そのメモリを最後に使用したことによってメモリに残されたもの、または完全にランダムなものです。角括弧括弧は、オペランドがポインタであり、アドレスのメモリの内容を示します。prbp - 24rbp - 16prbp - 16rbp - 16rbp - 16式のリテラル結果ではなく、コピーする必要がありますrbp - 16rbp - 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にコピーする場合。

他の人が言っているように、そのポインタはガベージ(メモリ内にたまたまあったもの)であるため、これがクラッシュする可能性は十分にあります(ただし保証はされません)。

于 2013-02-12T12:59:51.210 に答える