0

しばらくの間、x86 アセンブリで何かが混乱しました。NASM が操作のサイズを推測できる方法/タイミングです。例を次に示します。

mov ebx, [eax]

ここでは、eax に保持されているアドレスに格納されている 4 バイトを ebx に移動しています。レジスタが 32 ビットであるため、操作のサイズは 4 バイトと推測されます。

ただし、この操作は推論されず、コンパイル エラーがスローされます。

mov [eax], 123456

もちろん、解決策はこれです:

mov dword [eax], 123456

これにより、数値 123456 の 32 表現が、eax に保持されているアドレスに格納されているバイトに移動されます。

しかし、これは私を混乱させます。確かに eax が 32 ビットであることを確認できるので、mov の後に dword を指定しなくても 32 ビット値として保存したいと考えるべきではありませんか?

確かに、12345 の 16 ビット表現 (16 ビットに収まる小さい数値) を eax に入れたい場合は、次のようにします。

mov ax, 12345
4

3 に答える 3

4

オペランドのサイズは、メモリの宛先と直接のソースを持つ命令の場合、あいまいになります (したがって、指定する必要があります) 。(アドレス指定モードで 1 つ以上を使用している場合でも、どちらのオペランドも実​​際にはレジスタではありません。)

アドレスサイズとオペランドサイズは、命令の個別の属性です。


これがあなたの混乱の核心にあると思うので、別の答えのコメントであなたが言ったことを引用します:

mov [eax], 1メモリアドレスeaxに保持されている4バイトを1の32ビット表現に設定することを期待しています

BYTE/WORD/DWORD [PTR] 注釈は、メモリ アドレスのサイズに関するものではありません。そのアドレスのメモリ内の変数のサイズについてです。フラットな 32 ビット アドレッシングを想定すると、アドレスは常に 4 バイトの長さになるため、Exx レジスタに格納する必要があります。したがって、ソースオペランドが即値である場合、デスティネーションオペランドの dword (または何でも) 注釈は、アセンブラーが RAM の 1、2、または 4 バイトを変更することになっていることを知ることができる唯一の方法です。

これらの注釈が機械語コードに及ぼす影響を示すと、おそらく役立つでしょう。

$ objdump -d -Mintel test.o
...
   0:      c6 00  01             mov    BYTE PTR  [eax], 0x1
   3:   66 c7 00  01 00          mov    WORD PTR  [eax], 0x1
   8:      c7 00  01 00 00 00    mov    DWORD PTR [eax], 0x1

objdump(実際に印刷する方法と比較して、間隔を少し調整しました。)

2 つの点に注意してください: (1) 3 つの異なるオペランド プレフィックスは 3 つの異なるマシン命令を生成し、(2) 異なるプレフィックスを使用すると、マシン コードに出力されるソース オペランドの長さが変わります。

于 2015-06-20T22:30:22.583 に答える
3

mov [eax]、123456

この命令は、ソースオペランドに即時アドレッシングを使用し、デスティネーションオペランドに間接アドレッシングを使用します。つまり、指摘したように、レジスタeaxに格納されているメモリアドレスに10進数123456を配置しますが、eaxが指すメモリアドレス自体は32である必要はありませんビットサイズ。NASM は宛先オペランドのサイズを推測できません。レジスタ eax のポインタのサイズは 32 ビットです。

アドレスサイズとオペランドサイズは、命令のまったく別の属性です。

確かに、12345 の 16 ビット表現を eax に入れたい場合は、次のようにします: mov ax, 12345

はい。ただし、ここでは、ソース オペランドに即時アドレッシングを使用し、デスティネーション オペランドにレジスタ アドレッシングを使用しています。アセンブラは、宛先レジスタのサイズから移動するデータの量を推測できます (AX レジスタの場合は 16 ビットで、完全な EAX の上位 2 バイトは変更されないため、実際には 32 ビットを設定していません)。 EAX をその値に)。

コンパイルエラー

私はあなたがアセンブリエラーを意味したと思います:)

于 2015-06-20T22:15:59.287 に答える
2

最初のケースでは、EBX は 32 ビット レジスタであるため、問題なく決定できます。しかし、2番目のものでは、宛先レジスタとしてではなくアドレスとしてEAXを使用しているため、nasm開発者は安全なルートを取り、開発者にサイズを選択させます。

もしそうならmov [eax], 1、nasm はそれから何を判断できますか? メモリのバイト、16 ビット、または 32 ビット ブロックを 1 に設定しますか? 全く不明です。これが、開発者にサイズを明示させる方がよい理由です。

mov eax, 123456宛先がレジスターだからと言えば話は別ですが。

于 2015-06-20T22:09:18.697 に答える