如何在c /汇编中使用相对位置?

时间:2011-04-03 13:15:52

标签: c assembly fpic

据说位置无关代码仅使用相对位置而不是绝对位置,这是如何在c和汇编中分别实现的?

我们以char test[] = "string";为例,如何通过相对地址来引用它?

3 个答案:

答案 0 :(得分:2)

在C中,与位置无关的代码是编译器实现的细节。请参阅编译器手册以确定它是否受支持以及如何支持。

在汇编中,与位置无关的代码是指令集架构的细节。请参阅CPU手册,了解如何读取PC(程序计数器)寄存器,效率如何以及将代码地址转换为数据地址时建议的最佳实践。

由于在大多数现代操作系统上将代码和数据分成不同的页面,因此位置相关数据不太受欢迎。这是实现自包含可执行模块的好方法,但现在最常见的是病毒。

答案 1 :(得分:2)

在x86上,与位置无关的代码原则上如下:

        call 1f
1:      popl %ebx

然后使用ebx作为基指针,其位移等于要访问的数据与popl指令的地址之间的距离。

实际上它通常更复杂,通常可以使用微小的thunk函数来加载PIC寄存器:

load_ebx:
        movl 4(%esp),%ebx
        addl $some_offset,%ebx
        ret

选择偏移量,以便当thunk返回时,ebx包含指向程序/库中指定特殊点的指针(通常是全局偏移表的起点),然后是所有后续{ {1}} - 相对访问可以简单地使用所需数据和指定特殊点之间的距离作为偏移量。

在其他拱门上,原则上一切都相似,但可能有更简单的方法来加载程序计数器。许多只是让您在相对寻址模式下使用ebxpc寄存器作为普通寄存器。

答案 2 :(得分:0)

在伪代码中,它可能看起来像:

lea str1(pc), r0 ; load address of string relative to the pc (assuming constant strings, maybe)
st r0, test  ; save the address in test (test could also be PIC, in which case it could be relative
             ; to some register)

很大程度上取决于您的编译器和CPU架构,如前面的答案所述。找到的一种方法是使用适当的标志(-PIC -S for gcc)进行编译,然后查看你得到的汇编语言。