写一个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
答案 0 :(得分:0)
“无标签”和“与位置无关的代码”之间存在很大差异。你可以拥有一个,但不能拥有另一个,你可以拥有两者,你可以没有。
在没有标签的情况下制作上述代码并不是一件容易的事。而且我认为你没有理由要这么做。你能解释一下你正在做什么,这个任务背后的更大目标吗?
制作与位置无关的宏也很不寻常。通常,像整个子程序这样的东西与位置无关。再一次,为什么你认为你需要它呢?
尽管如此,上面代码中的所有跳转和调用指令都是eip
- 相对的(请参阅文档中的jmp / jcc和调用说明的详细信息)。
因此jne rest1
和jmp end1
不会使宏位置相关。无论代码位于何处,这些跳转始终以eip
递增一定量。
OTOH,出于同样的原因,call printf
(以及可能push LC1
)会使宏位置依赖。您可以通过将printf
和LC1
的地址作为附加参数(显式(与其他两个参数一样)或隐式(例如,在某些预定义的位置,寄存器或堆栈位置)传递到宏中来避免这种情况)。