1

NASMアセンブリでレジスタと定数の比較が機能しないのはなぜですか? 、1 バイトの変数 ( db) をEAXにコピーしていたことがわかりました。つまり、変数の後の 3 バイトもコピーされます。これがわかったので、同様のシナリオのコードを調べていると、次のことがわかりました。

では.data、配列とそのサイズが定数で定義されています。

array  db   1,2,3,4
size   equ  $-array

後で、.text私はこれを持っています:

mov EAX,size

これは私を驚かせました:そこで何が起こっているのですか?サイズはsize?バイトですか?単語?EAX は受信すべきではない余分なバイトを受信して​​いますか?

4

2 に答える 2

3

これは immediateであり、アセンブラーはそれに最も適切なサイズを選択する必要があります (可能なエンコーディングが複数ある場合)。可能な最小サイズがターゲット レジスタのサイズを超える場合、エラー、または少なくとも警告が表示されます。

あなたの例では、行mov EAX,sizeは入力したかのように組み立てられますmov EAX,4

于 2013-09-16T07:02:05.510 に答える
2

実際の位置から の開始点を引いた値から計算された即値ですarray。との重要な違いはequ、が使用されている場所で%defineコンパイラが$シンボルを直接置換するのに対し、 はコードの前処理時に役立つテキスト表現にすぎないため、は出現ごとに異なることです。対応するコードはequ%define$%define

array: db 1, 2, 3, 4
array_end: 
%define array_end - array

equ配列データ操作には完璧に見えるかもしれませんが、文字列に%defineは便利です。

コンパイラが命令に到達すると、正確には何が起こりますか?
定数の名前をすでに計算された値に置き換えるだけです。次に、コンパイラは命令を次のようにエンコードします。

mov r32, imm -> 0xB8 + 0x00 (for EAX)
size         -> 0x04 0x00 0x00 0x00

別のレジスターには異なる値があり、インテルのマニュアルに記載されています。への追加は、コードをバイト単位0xB8で格納するために使用される 1 バイトを節約する Intel のトリックです。REGModR/M

通常、命令はこのようなトリックを使用しませんが、頻繁に使用される命令の中には、アキュムレータ レジスタに特別なオペコードを使用して 1 バイトを節約するものがあります。

于 2013-09-16T13:06:19.063 に答える