简体   繁体   English

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

[英]How to use relative position in c/assembly?

It's said Position Independent Code only uses relative position instead of absolute positions, how's this implemented in c and assembly respectively? 据说位置独立码只使用相对位置而不是绝对位置,这又如何在c和汇编中实现?

Let's take char test[] = "string"; 我们来看char test[] = "string"; as an example, how to reference it by relative address? 作为一个例子,如何通过相对地址来引用它?

In C, position-independent code is a detail of the compiler's implementation. 在C中,与位置无关的代码是编译器实现的细节。 See your compiler manual to determine whether it is supported and how. 请参阅编译器手册以确定它是否受支持以及如何支持。

In assembly, position-independent code is a detail of the instruction set architecture. 在汇编中,与位置无关的代码是指令集架构的细节。 See your CPU manual to find out how to read the PC (program counter) register, how efficient that is, and what the recommended best practices are in translating a code address to a data address. 请参阅CPU手册,了解如何阅读PC(程序计数器)寄存器,效率如何以及将代码地址转换为数据地址时的推荐最佳实践。

Position-relative data is less popular now that code and data are separated into different pages on most modern operating systems. 由于在大多数现代操作系统上将代码和数据分成不同的页面,因此位置相关数据不太受欢迎。 It is a good way to implement self-contained executable modules, but the most common such things nowadays are viruses. 这是实现自包含可执行模块的好方法,但现在最常见的是病毒。

On x86, position-independent code in principle looks like this: 在x86上,与位置无关的代码原则上如下所示:

        call 1f
1:      popl %ebx

followed by use of ebx as a base pointer with a displacement equal to the distance between the data to be accessed and the address of the popl instruction. 然后使用ebx作为基指针,其位移等于要访问的数据与popl指令的地址之间的距离。

In reality it's often more complicated, and typically a tiny thunk function might be used to load the PIC register like this: 实际上它通常更复杂,通常可以使用微小的thunk函数来加载PIC寄存器,如下所示:

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

where the offset is chosen such that, when the thunk returns, ebx contains a pointer to a designated special point in the program/library (usually the start of the global offset table), and then all subsequent ebx -relative accesses can simply use the distance between the desired data and the designated special point as the offset. 选择偏移量时,当thunk返回时, ebx包含一个指向程序/库中指定特殊点的指针(通常是全局偏移表的起点),然后所有后续的ebx -relative访问都可以简单地使用所需数据与指定特殊点之间的距离作为偏移量。

On other archs everything is similar in principle, but there may be easier ways to load the program counter. 在其他拱门上,原则上一切都相似,但可能有更简单的方法来加载程序计数器。 Many simply let you use the pc or ip register as an ordinary register in relative addressing modes. 许多只是让你在相对寻址模式下使用pcip寄存器作为普通寄存器。

In pseudo code it could look like: 在伪代码中它可能看起来像:

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)

A lot depends on your compiler and CPU architecture, as the previous answer stated. 很大程度上取决于您的编译器和CPU架构,如前面的答案所述。 One way to find out would be to compile with the appropriate flags (-PIC -S for gcc) and look at the assembly language you get. 找到的一种方法是使用适当的标志(-PIC -S for gcc)进行编译,然后查看您获得的汇编语言。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM