9

在现代处理器中,可以从内存中加载一个寄存器,然后将索引指针修改为所需的值。例如,在我们的嵌入式处理器中,这将通过以下方式完成:

ldr r0, [r1], +12

这意味着 - 将 r1 指向的值加载到 r0 中,然后将 r1 增加 12:

r0 = [r1]
r1 = r1 + 12

在 C 语言中,使用指针算法,可以使用指针赋值,然后将指针前移 1:

char i, *p, a[3]={10, 20, 30};

p = &(a[0]);
i = *p++;
// now i==10 and p==&(a[1]).

我正在寻找一种方法来取消引用指针,同时通过一个非 1 的偏移量对其进行后期修改。这在 C 中是否可行,所以它可以很好地映射到类似的 asm 指令?

注意:

i = *p+=2;

在不修改指针的情况下增加 a[0] 中的值,并且:

i = *(p+=2);

预修改指针,所以在这种情况下i==30.

4

4 回答 4

7
  1. 是的,这是可能的。

  2. 你不应该做奇怪的指针数学来实现它。

  3. 不仅是关于优化设置,你的 GCC 后端需要告诉GCC 它有这样的特性(即当 GCC 本身被编译时)。基于这些知识,GCC 自动将相关序列组合成一条指令。

即如果你的后端写得对,甚至是这样的:

 a = *ptr;
 ptr += SOME_CONST;

应该成为一个单一的修改后指令。

编写后端时如何正确设置?(请您友好的邻居 GCC 后端开发人员为您做这件事):

如果您的 GCC 后端被调用foo

  1. 在 GCC 源代码树中,后端描述和挂钩将位于gcc/config/foo/.
  2. 在那里的文件(与 GCC 一起编译)中,通常有一个标题foo.h,其中包含许多#defines描述机器特性的文件。
  3. GCC 期望支持后增量的后端将宏定义HAVE_POST_INCREMENT为真,如果它支持后修改,则将宏定义HAVE_POST_MODIFY_DISP为真。(后增量 => ptr++,后修改 => ptr += CONST)。也许还有一些其他的事情需要处理。

假设您的处理器的后端已经做到了这一点,让我们来看看当您编译包含所述修改后序列的代码时会发生什么:

有一个特定的 GCC 优化过程通过属于此类别的指令对并将它们组合起来。该通行证的来源是这里,并且对 GCC 将做什么以及如何让它去做有一个相当清晰的描述。

但最终,这不是您作为 GCC 用户的控制范围。它由编写 GCC 后端的开发人员控制。正如最受好评的评论所说,您应该做的就是:

 a = *ptr;
 ptr += SOME_CONST;
于 2012-06-26T14:45:01.373 回答
3

你可以这样做,但不要这样做:

i = *((p += 2) - 2);

(不完全是后期修改)

于 2012-06-26T10:56:20.743 回答
1

我能想到的最接近的:

#define POST_INDEX_ASSIGN(lhs, ptr, index)  (lhs = *(ptr), (ptr) += (index))

POST_INDEX_ASSIGN(i, p, 2);
于 2012-06-26T11:59:54.090 回答
1
i = *p; 
p = (unsigned char*)p + 12;

其中 i 是任何类型,p 是指向该类型的指针。

如果您不添加类型转换,则指针增量将使用 size == 逐步完成sizeof(*p),这将使代码与发布的汇编程序完全不同。

例如,如果 pint*在 32 位系统上是 an,则指针将在没有类型转换的情况下增加 4*12 字节。

于 2012-06-26T13:53:42.637 回答