我想清理我的汇编代码并提供一种通过宏多次调用“NOP”的方法:
#define NOP() asm(" nop")
#define NOP_N( N ) \
NOP(); \
NOP(); \
.... call NOP() N times
我无法确定宏是否可以。
显然,出于性能原因,我不想要这样的东西:
#define NOP_N( n ) { register int i; for(i=0;i<n;i++) asm(" nop"); }
这违背了NOP的目的:
L17: ; NOP_N(3);
nop
addi 1,r0 ; Unsigned
cmpi 3,r0
blo L17
代码在C和汇编中,因此这里不能涉及C ++。此外,编译器相当陈旧,不支持可变参数宏...
答案 0 :(得分:4)
我认为无限制N
的解决方案是可能的。对于有界N
,您可以按以下方式执行操作:
#define REPEAT_0(WHAT)
#define REPEAT_1(WHAT) WHAT REPEAT_0(WHAT)
#define REPEAT_2(WHAT) WHAT REPEAT_1(WHAT)
#define REPEAT_3(WHAT) WHAT REPEAT_2(WHAT)
#define NOP_N(N) REPEAT_##N(asm("nop");)
第一部分可以轻松自动生成。第二部分采用的技术有时称为token pasting。
答案 1 :(得分:2)
this和Is the C preprocessor Turing complete?:
#define EVAL(...) EVAL1(EVAL1(EVAL1(__VA_ARGS__)))
#define EVAL1(...) EVAL2(EVAL2(EVAL2(__VA_ARGS__)))
#define EVAL2(...) EVAL3(EVAL3(EVAL3(__VA_ARGS__)))
#define EVAL3(...) EVAL4(EVAL4(EVAL4(__VA_ARGS__)))
#define EVAL4(...) EVAL5(EVAL5(EVAL5(__VA_ARGS__)))
#define EVAL5(...) __VA_ARGS__
AND REPEAT_INDIRECT
#define REPEAT(count, macro, ...) \
WHEN(count) \
( \
DEFER(REPEAT_INDIRECT) () \
( \
DEC(count), macro, __VA_ARGS__ \
) \
DEFER(macro) \
( \
DEC(count), __VA_ARGS__ \
) \
)
#define REPEAT_INDIRECT() REPEAT
//An example of using this macro
#define M(s, i, _) i
EVAL(REPEAT(8, M, ~)) // 0 1 2 3 4 5 6 7
AND FOREVER:
#define FOREVER() \
? \
DEFER(FOREVER_INDIRECT) () ()
#define FOREVER_INDIRECT() FOREVER
// Outputs question marks forever
EVAL(FOREVER())
答案 2 :(得分:0)
如果您真的想在预处理器中执行此操作(并且具有符合C99的编译器),则可以使用P99中的P99_UNROLL。
但是你完全低估了现代编译器能够实现的优化。只要边界是编译时常量,优秀的编译器就应该为您展开代码。查看汇编程序以确定(gcc有-S
)。
但你可能通过“正确”编码来帮助编译器:
#define NOP_N(N) for(register unsigned i=0; i < (N); i++) asm(" nop")
也就是说,让循环计数器在for
本地,并使用无符号类型,这样就不存在溢出的理论问题。