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

发布于 2024-10-29 21:53:30 字数 126 浏览 1 评论 0原文

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

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

It's said Position Independent Code only uses relative position instead of absolute positions, how's this implemented in c and assembly respectively?

Let's take char test[] = "string"; as an example, how to reference it by relative address?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

不打扰别人 2024-11-05 21:53:30

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

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

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

In C, position-independent code is a detail of the compiler's implementation. 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.

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.

与之呼应 2024-11-05 21:53:30

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

        call 1f
1:      popl %ebx

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

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

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

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

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

On x86, position-independent code in principle looks like this:

        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.

In reality it's often more complicated, and typically a tiny thunk function might be used to load the PIC register like this:

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.

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.

旧情别恋 2024-11-05 21:53:30

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

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)进行编译,然后查看获得的汇编语言。

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. 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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文