1)
非常に正確なタスク記述ないメモリ位置に64ビット整数0x0150と0x154
、64B整数0x0150から0x0157の位置でメモリ内にあります(合計8バイト)。この説明はデフォルトでメモリユニットdword
(32ビット)が使用されているように聞こえますが、16bリアルモードではそれはあまり意味のないデフォルトデータサイズではありません。
2)mov ax,0x0150
は、ax
に一定0x0150
こと読み込み、メモリから値をロードしません。あなたは、メモリの意志のすべての単語(3 * 4ワードのすべてのアドレスを入れたいならば今
mov si,0x0150 ; set si to contain address of input number1
mov ax,[si] ; load least significant 16b word (LSW) of it into ax
; you can even use absolute addressing like:
mov ax,[0x0150] ; usually not practical, but possible
:あなたは、メモリから実際の値をロードする場合は、例えばのようなそのメモリアドレス、間接参照する必要がありますnum1、num2、結果、すべて4ワード長)を使用すると、レジスタがすぐに使い果たされます。しかし、実際には、16bのモードで相対アドレッシングを使用することができますので、これは可能です:
mov si,0x0150 ; set si to contain address of input number1
mov ax,[si]
mov bx,[si+2]
mov cx,[si+4]
mov dx,[si+6]
; here dx:cx:bx:ax concatenated into single 64b number contains the number1
しかし、あなたはまた、減算により継続できるようnumber2のは、あまりにも数値1のベースアドレスによって対処することができます。
sub ax,[si+0x10] ; subtraction of LSW, ignoring CF (borrow)
sbb bx,[si+0x12] ; continuing by subtracting adjoining 16 bits
; but this time CF will affect the result, to make any "borrowing"
; happening while subtracting the LSW to propagate into upper 16 bits
... etc..
コメントの質問について... CFによって修正された結果はすでにbx
に保存されています。古いCFは失われています。CFには新しい "borrow"がbx - [0x162] - old_borrow
含まれています。 あなたが望むなら、どこかにCFを保存してください。CPUにはCFの値を検出/保存/設定する命令がありますが、数値を計算すると15 - 8は7、最終は7です。 "1"を借りて5から8を引いた
そして、あなただけのメモリ
mov [si+0x20],ax ; 0x0150 + 0x20 = 0x0170
mov [si+0x22],bx
...
に戻し、結果を保存することができますそして、私は基本的にあなたの全体の溶液を得たので、その結果アドレスは、NUM1アドレスに比較的計算することは、再び簡単です:/ ...それでは追加してみましょうあなたがそれをちょっと試してみるために、少なくともいくつかの情報が必要です。
あなたのような、単一64bの値を保持するために4 16bは、レジスタを使用せずに同じ操作を行うことができます。
mov ax,[si]
sub ax,[si+0x10]
mov [si+0x20],ax
mov ax,[si+2]
sbb ax,[si+0x10+2]
mov [si+0x20+2],ax
...
その1を見た後、あなたは素晴らしいアイデアを得ることができ、方法について:
mov ax,[si]
sub ax,[si+0x10]
mov [si+0x20],ax
add si,2 ; adjust rather base pointer then changing all those offsets
mov ax,[si]
sbb ax,[si+0x10]
mov [si+0x20],ax
...
を
動作しますか?もう違います。 add si,2
はCFを修正するので、次のsbb
は減算で「続行」しません。ここで学ぶべきことは、詳細な説明については、インストラクション・リファレンス・ガイドをよく調べることです。説明には、それが影響を与えるフラグが含まれます。 x86のでは - いくつかの命令はあなたを驚かせることができ、例えばに変更上記のコード:
mov ax,[si]
sub ax,[si+0x10]
mov [si+0x20],ax
inc si ; adjust base pointer
inc si
mov ax,[si]
sbb ax,[si+0x10]
mov [si+0x20],ax
...
が動作する、inc
はCFには影響しないので、唯一の他の算術フラグが変更されます。
フラグを変更しないで有効なアドレス指定レジスタに2を加算する別の方法は、lea si,[si+2]
です。あなたも、16bのリアルモードで使用できるようにBTWデフォルトでDOSBOX
は、386+をエミュレート:
mov si,0x0150
mov eax,[si]
mov ebx,[si+4] ; ebx:eax = 64b number1 (note +4 this time)
sub eax,[si+0x10]
sbb ebx,[si+0x14] ; ebx:eax = (number1 - number2)
mov [si+0x20],eax
...
あなたが唯一の8086(80286)命令セットを使用するように制約された場合を除き、32ビットのレジスタがで導入されました80386 CPU。
「SBB」命令を見て、下半分から上半分に借りて世話をする必要があります。 –
ありがとうございます。キャリーフラグを有効にして値を保存するだけですか?または、これらの値を使って何かをしなければならないので、データが読み込まれたときに正しい値が返されるようにする必要がありますか?申し訳ありませんが、この質問が理にかなっていない場合。 64ビットワードをまとめて戻さなければならない場合、キャリーフラグはこれに影響しますか? – Penrose5833
小学校での減算を覚えていますか?一度に1つの列を減算し、必要に応じて次の列から「借用」しますか? 64ビット値の各半分を列と考えてください。最初の 'SUB'から借りている場合は、' SUB'の代わりに 'SBB'命令を使用して、これを高次の減算に伝播する必要があります。 Googleの「x86 SBB」などと同じようなものがあります。 –