0

NASMマクロを記述します。divideには2つの引数があり、任意のアドレッシングモードで符号なし整数を指定します。マクロは、最初の引数の上限を2番目の引数で割った値を計算し、その結果をレジスタedxに配置します。2番目の引数が0(実行時にテストされる)の場合、結果は0になり、「ゼロ除算」というメッセージがstdoutに出力されます。

どちらがどれであるかをどのように判断できるので、それぞれのケースを処理できますか?(;アドレスモードは、レジスタ、メモリ、およびイミディエートです。)

編集:これは私が書いた最後のコードです:ラベルなしでこのコードを書く方法は?(位置独立コード):

%macro divide 2

section .rodata
        LC1: DB "divide by zero ", 10, 0

section .text

  mov eax, %1
  mov ebx, %2
  cmp ebx, 0 ; divide by zero
  jne rest1
  push LC1
  call printf
  add esp,4
  mov edx, 0
  jmp end1

rest1:
  mov edx, 0
  div ebx
  add eax, edx
  mov edx , eax ; the result should be in edx

end1:
 %endmacro
4

1 に答える 1

1

どちらがどちらかを判断する必要はありません。任意の場所(別のレジスタ、メモリ、イミディエート定数)からEAXの命令で可能なような汎用レジスタのロード。MOVそれを利用してください。

編集

さらに明確にするために、次のようなマクロを作成する方法を説明します。

%macro mydiv 2
  mov eax, %1
  mov ebx, %2
  mov edx, 0
  div ebx
%endmacro

そして、これはあなたがそれをどのように使うかです:

  mydiv 3, 2 ; 2 immediate operands

  mov ebx, 15
  mov ecx, 3
  mydiv ebx, ecx ; 2 register operands

  mydiv [dividend], [divisor] ; 2 memory operands

...

  dividend dd 42
  divisor  dd 6

もちろん、マクロの定義方法は、除算オペランドを配置できる場所に特定の制限を課します。たとえば、オペランド2(除数)は、前の命令が被除数をに入れるため、オペランド1(被除数)でロードされるEAXため、入れることができません。mov ebx, eaxEBXmov eax, %1EAX

スタックを使用してこれを回避できます。

%macro mydiv2 2
  push  ebx
  push  %1
  push  %2
  pop   ebx
  pop   eax
  mov   edx, 0
  div   ebx
  pop   ebx
%endmacro

このマクロは、レジスタからの除数と被除数を問題なく受け入れ、ゴミ箱に入れませんEBX。それに関する唯一の(マイナーな)問題は、オペランドがメモリ内にあり、以下に関連してアドレス指定されているESP場合です。

mydiv2 eax, [esp+8]

それらのプッシュは変化ESPし、それを説明する必要があります。

EDIT2

注意点が1つありmydiv2ます...16ビットモードでは16ビット、32ビットモードでは32ビットとしてイミディエート定数(123など)をプッシュしますが、32ビットのものとしてポップします。16ビットモードで動作させる には、即値定数の前に:mydiv2を付ける必要があります。dword

  mydiv2 dword 3, dword 2 ; 2 immediate operands

これで、必要な残りの機能をマクロに実装できます。

于 2012-06-24T11:16:25.790 に答える