2017-10-22 9 views
1

:私はレジスタ%eaxにはそれに値を持っていますが、-8(%のRBP)を知っている空のレジスタでaddを使用していますか?私はこのようになりますアセンブリコードを見てい

addl %eax, -8(%rbp) 

は、前の行にタッチされていません。空であると仮定して、%eax + 0の値を-8(%rbp)に入れるだけですか?

+2

いいえ以前は必ず割り当てられていましたが、もっと見る必要があります。別のポインタを使用して記述されている可能性があります。 'rsp'に対して相対的です。メモリは通常ゼロにならないことに注意してください。特に 'rbp'が頻繁に指し示すスタックではありません。 – Jester

答えて

4

@Jesterはコメント内で指摘したように、その行の前のどこかに値を割り当てる必要があります。それ以外の場合は、未定義の可能性のある動作が考えられます。

だが考慮以下のCのソースコード及び(GCCでコンパイルなし最適化)それぞれのアセンブリ出力を見てみましょう:

ファイルadd_1_noinit.c

int main(void) { 
     int a; 

     return a += 1; 
} 

ファイルadd_1_noinit.s (gcc -O0 -S add_1_noinit.c):

... snip ... 
.LFB0: 
     .cfi_startproc 
     pushq %rbp 
     .cfi_def_cfa_offset 16 
     .cfi_offset 6, -16 
     movq %rsp, %rbp 
     .cfi_def_cfa_register 6 
     addl $1, -4(%rbp) 
     movl -4(%rbp), %eax 
     popq %rbp 
     .cfi_def_cfa 7, 8 
     ret 
     .cfi_endproc 
.LFE0: 
... snip ... 

ご覧のとおり、add_1_noinit.cは変数に初期化しないため、未定義の動作になります(戻り値main()は不明です)。

ファイルadd_1_init.c

int main(void) { 
     int a = 0; 

     return a += 1; 
} 

ファイルadd_1_init.s(gccの-O0 -S add_1_init

今度は、初期化変数の出力を見てみましょう。 c):

... snip ... 
.LFB0: 
     .cfi_startproc 
     pushq %rbp 
     .cfi_def_cfa_offset 16 
     .cfi_offset 6, -16 
     movq %rsp, %rbp 
     .cfi_def_cfa_register 6 
     movl $0, -4(%rbp) 
     addl $1, -4(%rbp) 
     movl -4(%rbp), %eax 
     popq %rbp 
     .cfi_def_cfa 7, 8 
     ret 
     .cfi_endproc 
.LFE0: 
... snip ... 

ご覧のとおり、我々は主()の戻り値が何であるかを知っているこの例では、値0 は、それにを添加する前-4(%のRBP)が指し示すメモリ領域に設定されています。

+0

したがって、-8(%rbp)はその行より前には言及されておらず、%rspを使用する参照もありませんが、-24(%rbp)に格納されている配列ポインタがあります。 -8(%rbp)はその配列の5番目の要素を格納しますか?私はポインタが配列のメモリ内のどこかを指していると思ったので、これは正しいとは思わない。私は完全に迷っています。 – wenjay

2

一般に、シリコンの格納ビットは2つの状態0と1しか持たないため、そのレジスタを設定するコードが表示されていなくても、パターンは "空"ではなく、命令はパターンを使用して、 。さて、ロジックのシミュレーションでは、ビット0,1、xに対して3つ以上の状態を持つことができます。ここでxはxであり、anyredはxであり、xはxです。その場合、 "空"または少なくとも初期化されていないレジスタを持つことができます。 Xesは、あなたのシミュレーションに感染してしまい、最終的にはすべてのものをxesに変えます。だから、あなたが読む前に常に書くことに非常に注意する必要があります。レジスタを含む。

この場合、有効なコードであれば、その命令の前のある時点で、rbpが正当な値で書かれていました。どのように分解したり、これを見ているかによっては、コードとして分解したデータパターンがあります。 x86を正しく解体することは不可能ではありません。したがって、これが逆アセンブルされたコードであれば、パーセンテージが間違っているか間違っていると考える必要があります。これがコンパイラからのまっすぐアセンブリであるか手作業で書かれていて、それが悪いコードではないと仮定すると、書かれているレジスタを見るために先行するコードや呼び出しで十分に戻っていません。

注意レジスタは「空」にすることはできません。ビットは状態を持ち、ビット記憶には空の状態はありません。ゼロまたは1だけです。

関連する問題