次の例では、アセンブリ命令MOVSX
はどのように機能しますか。
MOVSX ECX,BYTE PTR DS:[EDX]
この場合、レジスターの状態は次のとおりです。
ECX = 0000000F
EDX = 0012FD9F
私の考えでは、[EDX] = 9Fの最後のバイトが必要で、それをECXに移動してから、16ビット= 0000009Fに一致するように符号拡張します。ただし、実際の結果は00000016です。誰かが私がどこが間違っているのか説明してもらえますか?
それは部分的に正しいです。しかしながら:
BYTE PTR DS:[EDX]
はEDXに保持されているアドレスにあるバイトを取得します。このバイトはECX
から最下位バイトにコピーされ、残りはバイトの符号で埋められます。
予期しない結果の場合、これはメモリアドレスで10x12FD9F
バイト0x16
位置しています。
ノート:
DS:
ここでは必要ありません。 [EDX]
は自動的にDS
を参照します。1 「メモリアドレス」とは、ここでは仮想メモリまたは物理メモリを指します
多くのIntel/AMD x86命令は「modrm」形式で利用可能です-それらには2つのオペランドがあり、一方はレジスタでなければならず、もう一方はレジスタまたはメモリ参照であり、そのアドレスはmodrmバイトによって決定されます命令のエンコーディング、および場合によってはsib(スケーリングされたインデックスバイト)などの命令の後続のバイト、および直接の定数/メモリオフセット。また、可能なセグメントプレフィックスバイト。
通常、これらは次の形式のreg、reg/mem命令です
rsrcdst += rsrc
or
rsrcdst += Memory[ ... addressessing mode ...]
ただし、x86アセンブリコードには、これらの命令のreg、regおよびreg、mem形式の個別のオペコード/命令ニーモニックはありません。オペランドがレジスターであるかメモリー・ロケーションであるかは、アセンブラーでアセンブリー構文によって示されます。
この場合、アセンブリコードは
MOVSX ECX、BYTE PTR DS:[EDX]
命令オペコードはMOVSXです。
宛先オペランドはレジスタECXです。
ソースオペランドは「BYTE PTR DS:[EDX]」です。これがメモリ参照であることは、いくつかのことで示されます。(1) "[EDX]"を囲む角括弧-角括弧は、Memory [... address ...]の省略形です。 (2)「DS:」接頭辞。データセグメント内にあることを示します。レジスタオペランドには、このようなセグメントプレフィックスはありません。 (3)「BYTE PTR」-「「DS:[EDX]」で指定されたメモリアドレスを取得し、それをメモリ内の8ビットバイトを参照していると解釈します」.
あなたが本当に欲しいのは
MOVSX ECX,DL
「DL」は、32ビットレジスタEDXの下位8ビットの名前です。つまりDL = EDX.bits [7:0]。残念ながら、x86アセンブラーは通常、「EDX.bits [7:0]」のような構文を受け入れません(私が書いた場合を除く)。そのため、サブレジスターの歴史的な名前を知る必要があります。
AL = EAX.bits[7:0]
AH = EAX.bits[15:8]
AX = EAX.bits[15:0]
EAX = 32 bit register that "covers" all of the above
など:BL、CL、DL、DI、...