8086 アセンブリ プログラミングでは、データをセグメント レジスタにロードするには、最初にデータを汎用レジスタにロードしてから、この汎用レジスタからセグメント レジスタに移動する必要があります。
直接ロードできないのはなぜですか?許可されない特別な理由はありますか?
mov ax,5000H
とはどう違いmov ax,[5000H]
ますか?[5000h]
メモリロケーション 5000h の内容を意味しますか?
8086 アセンブリ プログラミングでは、データをセグメント レジスタにロードするには、最初にデータを汎用レジスタにロードしてから、この汎用レジスタからセグメント レジスタに移動する必要があります。
直接ロードできないのはなぜですか?許可されない特別な理由はありますか?
mov ax,5000H
とはどう違いmov ax,[5000H]
ますか?[5000h]
メモリロケーション 5000h の内容を意味しますか?
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/stdout
16 ビット モードでフラット バイナリをアセンブルし、リストを生成します。
手動で編集して、バイトを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 のオペコードをmov
Sreg に割くことができなかったのでしょうか? この設計上の決定は理にかなっています。どのくらいの頻度でセグメント レジスタをリロードする必要がありますか? 非常にまれですが、実際の大規模なプログラムでは、定数を使用しないことがよくあります(私は思います)。しかし、静的データを使用するコードでは、アキュムレータをループ内の固定アドレスにロード/ストアする可能性があります。(8086 はコードフェッチが非常に弱いため、ほとんどの場合、コードサイズ = 速度です)。
mov Sreg, r/m16
また、追加の命令 ( など) を 1 つ追加するだけで、アセンブル時の定数に使用できることにも注意してくださいmov ax, 4321h
。しかし、もし だけだったらmov Sreg, imm16
、ランタイム変数のセグメント値には自己変更コードが必要だったでしょう。(したがって、ソース バージョンを省略しないことは明らかですr/m16
。) 私のポイントは、1 つだけを使用する場合は、間違いなくレジスタ/メモリ ソース バージョンになるということです。
昔、その理由を読んだ記憶があります。目の前にその書類がありませんので、手を振ることをお許しください。
メモリ位置または定数からセグメント レジスタをロードするには、メモリ サイクルが必要です。メモリのアラインメントが乱れると、16 ビット値を読み取るのに 2 メモリ サイクルかかる場合があります。サイクル間では、セグメント レジスタの値は無効です。ここで、スタック セグメント レジスタをいじっていて、割り込みが発生したとします。これが手押し車です。乗り物を楽しんでください!