Assembly NASM宏处理任何寻址模式

Assembly NASM宏处理任何寻址模式,assembly,macros,x86,nasm,addressing-mode,Assembly,Macros,X86,Nasm,Addressing Mode,编写一个NASM宏:divide,它有两个参数,用于在任何寻址模式下指定无符号整数。宏计算第一个参数的上限除以第二个参数,并将结果放入寄存器edx。如果第二个参数为0(将在运行时测试),则结果应为0,并且应将消息“除以零”打印到stdout 我怎样才能分辨哪个是哪个,这样我们就可以处理每个案件? (;地址模式有:寄存器、内存和立即数。) 编辑: 这是我写的最后一段代码: 如何编写没有标签的代码?(位置独立代码): 你不需要分辨哪个是哪个。使用MOV指令可以从任何位置(另一个寄存器、内存、立即数常

编写一个NASM宏:divide,它有两个参数,用于在任何寻址模式下指定无符号整数。宏计算第一个参数的上限除以第二个参数,并将结果放入寄存器edx。如果第二个参数为0(将在运行时测试),则结果应为0,并且应将消息“除以零”打印到stdout

我怎样才能分辨哪个是哪个,这样我们就可以处理每个案件? (;地址模式有:寄存器、内存和立即数。)

编辑: 这是我写的最后一段代码: 如何编写没有标签的代码?(位置独立代码):


你不需要分辨哪个是哪个。使用
MOV
指令可以从任何位置(另一个寄存器、内存、立即数常量)加载通用寄存器,如
EAX
。好好利用这一点

编辑

更清楚地说,您可以这样编写宏:

%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(除数)不能在
EAX
中,因为
mov ebx,EAX
将使用操作数1(被除数)加载
ebx
,因为前面的指令
mov EAX,%1
将被除数放入
EAX

您可以使用堆栈解决此问题:

%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]
这些推动改变的因素必须加以考虑

EDIT2

mydiv2有一个警告。。。在16位模式下,它会将立即数常量(如123)推送为16位,在32位模式下推送为32位,但会将它们作为32位常量弹出。要使
mydiv2
在16位模式下工作,需要在立即数常量前面加上
dword

  mydiv2 dword 3, dword 2 ; 2 immediate operands

现在,您可以在宏中实现所需的其余功能。

但是eax可以是一个值,也可以是一个地址。否?
EAX
是一个寄存器。它可以包含不同的值。一般来说,这些地址是不是由你决定。只需宏中的
MOV寄存器、参数
。当你调用这个宏时,这个参数可以是123,ECX,[EBX*4+EDI-3],任何你想要的。谢谢!我还有一个问题:在假设参数有效的情况下(即,如果它们引用内存地址,即使代码被移动,这些地址仍然有效),重新编写上述宏以仅生成严格位置独立的代码。-->>为什么standart代码会有问题(就像你们写的那个样)?我的宏将汇编成独立于位置的代码本身。唯一可以使其位置相关的是作为参数提供给它的内存操作数。但这是你需要考虑的。或者以登记簿和/或即时的形式提供。我相信我已经回答了最初的问题。请撤消问题更改并询问另一个有关位置独立代码的问题。
  mydiv2 dword 3, dword 2 ; 2 immediate operands