C / C ++索引跳转到一组NOP中

时间:2019-02-24 22:51:33

标签: c delay indexed nop

我想产生一个时钟分辨率的延迟,所以我的想法是一个接一个地处理255个NOP,然后跳到最后一个减去所需的延迟。因此0会跳过最后一个NOP,1会跳过最后一个NOP,255会跳过第一个NOP。

我以前使用过索引函数调用,但是在这样的索引goto上找不到任何东西。我还考虑过使用switch语句,但这似乎还有其他说明。

任何收到建议的人。

1 个答案:

答案 0 :(得分:0)

Nick ODell有一个不错的解决方案,但是编译器无法知道您所有的情况都只有一个字节的代码。直到汇编器通过后才知道。因此,无论在每种情况下生成多少代码,编译器都必须生成能够工作的东西,而间接跳转表确实是实现此目的的唯一方法。

因此,我认为,为了获得“理想的”代码(每个nop占用一个字节),您还必须在汇编中编写跳转逻辑。

这就是我想出的(对于Linux上的gcc / amd64 / gas)。 Here it is on godbolt

#include <stdlib.h>

#define N 1000

#define xstr(s) str(s)
#define str(s) #s


void delay(unsigned ticks) {
  if (ticks <= N) {
    asm("movq $1f, %%rax \n"
    "addq %0, %%rax \n"
    "jmp *%%rax \n"
    "1: \n"
    ".rept " xstr(N) " \n"
    "nop \n"
    ".endr \n"
    : : "g" ((unsigned long)(N-ticks)): "ax");
  } else {
    abort();
  }
}

int main(void) {
  delay(4);
  return 0;
}

请注意,必须使用-no-pie进行编译。如果希望它用作与位置无关的可执行文件,则可能需要使用call 2f ; 2f: popq %rax之类的技巧将绝对程序地址保存到寄存器中。

当然,总是有一个问题,实际获取此代码的开销是否会破坏您的延迟时间的准确性...