2016-05-04 15 views
2

単純なプロシージャーをx86-64アセンブリーで記述しようとしていますが、単純にint配列の長さを戻しています。配列の最後の要素は0で、これは数えてはなりません。配列はCコードからint *として渡されます。x86-64アセンブリー(AT&T構文)の配列要素の比較

次のように私のアセンブリコードは次のとおりです。

f1: 
    movq $0, %rax # zero out %rax 
    jmp test  # jump to test 
body: 
    incq %rax  # increment %rax, which is counter and array index 

test: 
    cmpq $0, (%rdi,%rax,4) # compare (rdi + (rax * 4)) to 0 
    jne body # jump if zero flag is not set 
ret 

これを実行すると、私はどちらか正しいが、乱暴に間違っていないではない結果を取得し、その代わりに11(配列のサイズ渡さマイナス0期)私は38を得る。私が考えているのは、私の比較ステートメントが間違っているということです。私の考えは、cmpqがレジスタを変更せずに(dest - src)実行するので、配列インデックスが0の場合は0から0になるので、ゼロフラグが設定されますが、それは起こっていないようです。任意の助けをいただければ幸い

movq (%rdi,%rax,4), %rax # %rax initially 0, so first element loaded into %rax 

Iは、任意の正しい値を返す%のRAX、中に配列の任意の要素を読み込むことができます!

+0

あなたのコードは非常に短く、あなたが考えるべきことをしていない部分だけを保ちました。あなたが思っていたことを説明するために、 –

答えて

2

intは、x86-64 ABI(SystemVとWindows)の両方で32ビット(4バイト)です。 (詳細は、タグwikiを参照してください)。

cmpq $0, (%rdi,%rax,4)は、正確にインデックスを4で調整しますが、ですが、誤って64ビットのオペランドサイズを使用します。 (クワッドワードためqスタンド。インテルx86の用語では、「言葉」は、16ビットである。)

cmpqは、2つの連続する要素を比較しました。同等のCは、x86のwhile(0 != *(int64_t*)&(array[i])){ ++i; }


外になり、言葉は通常、そのような機械か何かのレジスタサイズなので、longのサイズと一致します。例えばワードは32ビットMIPSで32ビットです。

それはちょうど用語だし、それは言葉(& T構文wサフィックスAT)、DWORD(l接尾辞)、QWORD(q接尾辞)のような便利な名前を用意しておくと便利です。 x86のをデバッグする場合でも、いくつかの場所でgdb

、 "言葉" は32ビットである(例えば、メモリをダンプするxコマンドはb(バイト)、h(ハーフワードがあります:16b)は、w(ワード)、およびg(巨人を:8B)size format specifiers

+0

非常にありがとう、余分なトリビアのために私は 'cmpl'に指示を変更し、正しい値が返されていますが、なぜ私は理解できないのですか?オペランドサイズがスケーリングに影響していますか?オフセットの値? – joezuu

+0

@ joezuu:いいえ、あなたのアドレッシングは常に正しいです。 'cmpq'が実際にやっていたもので答えを更新しました。 –

関連する問題