我想产生一个时钟分辨率的延迟,所以我的想法是一个接一个有255个NOPs,然后跳到最后一个减去所需的延迟。所以0将跳过最后一个NOP,1跳到最后一个NOP,255跳到第一个NOP。
我以前使用过索引函数调用,但在这样的索引goto上找不到任何内容。我也想过使用switch语句,但这似乎有其他指令。
收到任何建议,不胜感激。
最佳答案
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
这样的技巧来将绝对程序地址放入寄存器中。当然,总是有这样一个问题:实际获取此代码的开销是否会扰乱延迟时间的准确性。。。
关于c - C/C++索引跳转到一组NOP中,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/54857340/