2017-03-07 6 views
2

メモリ位置0x0150および0x0154の64ビット整数を0x0160および0x0164の64ビット整数から減算するプログラムを作成します。メモリ位置0x0170と0x0174に結果を格納します。8086アセンブリで2つの64ビット整数を減算する方法

私は64ビットをレジスタに収めることができないので、それをより小さな部分に分割するという論理を理解しています。そして、私たちが最初に最も重要でない部分を引くことを知っています。私はそれを実際にコーディングするのに苦労しています。どのGPIOを使用するかは重要ですか?これは私の例なので、私はどう思っているのか分かります。たぶん私はそれほど遠くはないが、それはそれのように感じる。

MOV AX, 0X0150 
MOV BX, 0X0154 
MOV CX, 0X0160 
MOV DX, 0X0164 
SUB BX, DX 
SUB AX, CX 
MOVE 0X0174, BX 
MOVE 0X0170, AX 

64ビット整数の各半分をレジスタに格納しました。次に、レジスタを引いて、それらをメモリ位置に入れます。その16進形式は大丈夫ですか?それとも0174hのようなものにする必要がありますか?

これが何とか正しい場合でも、これを実際にコンパイルするには、return文またはヘッダなどが必要ですか? (私はNASMとDosBoxを使用しています)

これは私が書かなければならない12の類似プログラムの最初のものです。正しい方向へのどんなプッシュも、うまくいけば私を私の道に導くでしょう!

+1

「SBB」命令を見て、下半分から上半分に借りて世話をする必要があります。 –

+0

ありがとうございます。キャリーフラグを有効にして値を保存するだけですか?または、これらの値を使って何かをしなければならないので、データが読み込まれたときに正しい値が返されるようにする必要がありますか?申し訳ありませんが、この質問が理にかなっていない場合。 64ビットワードをまとめて戻さなければならない場合、キャリーフラグはこれに影響しますか? – Penrose5833

+0

小学校での減算を覚えていますか?一度に1つの列を減算し、必要に応じて次の列から「借用」しますか? 64ビット値の各半分を列と考えてください。最初の 'SUB'から借りている場合は、' SUB'の代わりに 'SBB'命令を使用して、これを高次の減算に伝播する必要があります。 Googleの「x86 SBB」などと同じようなものがあります。 –

答えて

3

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。

+0

を "0x0150と0x154の除算"というように使ってください... "0x0160と0x164から"私は32ビットレジスタ(0x0170/4 = 0x0150/4-0x160/4)を使用することができます。 0x0154は最初の値の後半で、2番目の – Tommylee2k

+0

@ Tommylee2kではなく、おそらくはいですが、彼は自分のコードで 'ax'だけを使っていました...おそらく' eax'、 'ax'と'彼らはまだ混乱していますか?私は答えの最後に32bレジスタを追加しました。しかし、純粋な16bバージョンと比較することができれば、実際には問題ありません。データタイプを変更しているときに、どのような調整が必要ですか。 :) – Ped7g

+0

私はあなたが正しいと思うが、あなたの "btw:"部分はより良い答えだったが、あなたの現在の答えは助けてくれる以上に彼を混乱させるかもしれない;)しかし、16ビットか32ビットを開発している本当にこれを決める。私は教授が何らかのキットに16進数入力の8086アセンブリを教えていることを知っています – Tommylee2k

関連する問題