在宏组装中定位独立代码

时间:2012-06-25 07:21:49

标签: assembly x86 nasm

写一个NASM宏:divide,它有2个参数,在任何寻址模式下都指定无符号整数。宏计算其第一个参数的上限除以第二个参数,并将结果放在寄存器edx中。如果第二个参数为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

1 个答案:

答案 0 :(得分:0)

“无标签”和“与位置无关的代码”之间存在很大差异。你可以拥有一个,但不能拥有另一个,你可以拥有两者,你可以没有。

在没有标签的情况下制作上述代码并不是一件容易的事。而且我认为你没有理由要这么做。你能解释一下你正在做什么,这个任务背后的更大目标吗?

制作与位置无关的宏也很不寻常。通常,像整个子程序这样的东西与位置无关。再一次,为什么你认为你需要它呢?

尽管如此,上面代码中的所有跳转和调用指令都是eip - 相对的(请参阅文档中的jmp / jcc和调用说明的详细信息)。

因此jne rest1jmp end1不会使宏位置相关。无论代码位于何处,这些跳转始终以eip递增一定量。

OTOH,出于同样的原因,call printf(以及可能push LC1)会使宏位置依赖。您可以通过将printfLC1的地址作为附加参数(显式(与其他两个参数一样)或隐式(例如,在某些预定义的位置,寄存器或堆栈位置)传递到宏中来避免这种情况)。