22

8086 アセンブリ プログラミングでは、データをセグメント レジスタにロードするには、最初にデータを汎用レジスタにロードしてから、この汎用レジスタからセグメント レジスタに移動する必要があります。

直接ロードできないのはなぜですか?許可されない特別な理由はありますか?

mov ax,5000Hとはどう違いmov ax,[5000H]ますか?[5000h]メモリロケーション 5000h の内容を意味しますか?

4

4 に答える 4

12

x86 マシン コードには、move-to-Sreg 用のオペコードが 1 つしかありません。そのオペコードは
8E /r mov Sreg, r/m16であり、レジスタまたはメモリ ソースを許可します(ただし、即時ではありません)。

他の回答のいくつかの主張に反して、アドレスの2バイトが現在のモードに役立つセグメント値を保持していると仮定して、mov ds, [5000h]問題なく実行5000hされます(数値として直接使用されるリアルモードと、Sreg値がセレクターである保護されたモードLDT / GDT にインデックスを付ける)。

x86 では、命令の即時形式 (マシン コードの一部としてエンコードされた定数を使用) とレジスタ/メモリ ソース バージョンに対して常に異なるオペコードが使用されます。たとえばadd eax, 123、 とは異なるオペコードにアセンブルしadd eax, ecxます。ただし、ModR/M バイトが異なるだけで、add eax, [esi]と同じadd r, r/m32オペコードです。add eax, ecx


からの NASM リスト、nasm sreg.asm -l/dev/stdout16 ビット モードでフラット バイナリをアセンブルし、リストを生成します。

手動で編集して、バイトをopcode modrm extra. これらはすべて 1 バイトのオペコード (ModRM バイトの /r フィールドにスペースを借りる余分なオペコード ビットはありません) であるため、最初のバイトを見て、それがどのオペコードであるかを確認し、2 つの命令が同じオペコードを共有していることに注意してください。

   address    machine code         source           ;  comments
 1 00000000 BE 0050           mov si, 5000h     ; mov si, imm16
 2 00000003 A1 0050           mov ax, [5000h]   ; special encoding for AX, no modrm
 3 00000006 8B 36 0050        mov si, [5000h]   ; mov r16, r/m16 disp16
 4 0000000A 89 C6             mov si, ax        ; mov r/m16, r16
 5                                  
 6 0000000C 8E 1E 0050        mov ds, [5000h]   ; mov Sreg, r/m16
 7 00000010 8E D8             mov ds, ax        ; mov Sreg, r/m16
 8                                  
 9                            mov ds, 5000h
 9          ******************       error: invalid combination of opcode and operands

エンコーディングをサポートするmov Sreg, imm16には、別のオペコードが必要です。これにより、8086 をデコードするために余分なトランジスタが必要になり、将来の拡張のための余地が少なくなり、より多くのオペコード コーディング スペースが使用されます。8086 ISA のアーキテクトが、これらのうちどれをより重要と見なしたかはわかりません。

8086 にはmov AL/AX, moffs、絶対アドレスからアキュムレータをロードするときに 1 バイトを節約する特別なオペコードがあることに注意してください。しかし、-immediate のオペコードをmovSreg に割くことができなかったのでしょうか? この設計上の決定は理にかなっています。どのくらいの頻度でセグメント レジスタをリロードする必要がありますか? 非常にまれですが、実際の大規模なプログラムでは、定数を使用しないことがよくあります(私は思います)。しかし、静的データを使用するコードでは、アキュムレータをループ内の固定アドレスにロード/ストアする可能性があります。(8086 はコードフェッチが非常に弱いため、ほとんどの場合、コードサイズ = 速度です)。

mov Sreg, r/m16また、追加の命令 ( など) を 1 つ追加するだけで、アセンブル時の定数に使用できることにも注意してくださいmov ax, 4321h。しかし、もし だけだったらmov Sreg, imm16、ランタイム変数のセグメント値には自己変更コードが必要だったでしょう。(したがって、ソース バージョンを省略しないことは明らかですr/m16。) 私のポイントは、1 つだけを使用する場合は、間違いなくレジスタ/メモリ ソース バージョンになるということです。

于 2017-12-05T11:19:00.817 に答える
-2

昔、その理由を読んだ記憶があります。目の前にその書類がありませんので、手を振ることをお許しください。

メモリ位置または定数からセグメント レジスタをロードするには、メモリ サイクルが必要です。メモリのアラインメントが乱れると、16 ビット値を読み取るのに 2 メモリ サイクルかかる場合があります。サイクル間では、セグメント レジスタの値は無効です。ここで、スタック セグメント レジスタをいじっていて、割り込みが発生したとします。これが手押し車です。乗り物を楽しんでください!

于 2016-07-28T15:29:36.997 に答える