C/C++宏重复代码

pobjuy32  于 7个月前  发布在  C/C++
关注(0)|答案(5)|浏览(91)

有没有办法用一个宏将一个C代码重复N次?N也是一个宏。
例如,如果我有这个宏:

#define N 5  
#define COODE "nop\n\t"
#define REPEAT [...]

字符串
当我调用repeat时,预处理器会写入CODE N次,所以

__asm__(REPEAT);


将成为

__asm__("nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t");


我有一个Arduino,必须等待一个确切的(和小,大约10-15)时钟的数量。每个“nop”(无操作)只需要一个时钟周期来执行,它什么也不做。我不能只做一个周期,因为每个周期都在多个操作中执行(初始化计数器,递增计数器,检查是否到达终点),所以我不想手动写“nop\n\t”,我想有一个宏。这样我也可以简单地改变N来修改程序,而不需要重写它。
提前感谢您

zsohkypk

zsohkypk1#

如果不想包含整个库或不使用define,可以使用 simple 递归模板:

//By Christopher Andrews, released under MIT licence.

template< unsigned N > struct Nops{
  static void generate() __attribute__((always_inline)){
    __asm__ volatile ("nop");
    Nops< N - 1 >::generate();
  }
};
template<> struct Nops<0>{ static inline void generate(){} };

void setup() {
  Nops<10>::generate();
}

void loop(){}

字符串
这将生成所需的nop的确切数量。
0000010 a设置:
上午10时00分
上午10点整
上午10时00分
晚上11点00分
上午11时00分
上午11时00分
上午11点00分
上午11点00分
上午11时00分
上午11时00分
上午11点08分,下午95分
我已经在Arduino的TFT驱动程序中使用了这种方法。

编辑:

在用avr-gcc编译的AVR上,还有另一种方法可以轻松地做到这一点。我假设这在旧的工具链上可能不可用。
为了将执行延迟特定的周期数,GCC实现了
void __builtin_avr_delay_cycles (unsigned long ticks) ticks是延迟执行的ticks数。请注意,这个内建并未将中断的影响纳入考量,因为中断可能会增加延迟时间。ticks必须是编译时间整数常数;不支援周期数可变的延迟
从这里开始:https://gcc.gnu.org/onlinedocs/gcc-4.7.1/gcc/AVR-Built_002din-Functions.html

epggiuax

epggiuax2#

下面的代码使用GNU C,

#define NOP __asm__("nop")

#define ten(a)     a;a;a;a;a;a;a;a;a;a
#define hundred(a) ten(ten(a))

int
main()
{
    hundred(NOP);
    return 0;
}

字符串
编译和调试:

code@lab:~/debug$ gcc -g -o debug_NOP debug_NOP.c
code@lab:~/debug$ gdb -q --nh debug_NOP
Reading symbols from debug_NOP...done.
(gdb) set disassembly-flavor intel
(gdb) start
Temporary breakpoint 1 at 0x664: file debug_NOP.c, line 10.
Starting program: /home/code/debug/debug_NOP 

Temporary breakpoint 1, main () at debug_NOP.c:10
10      hundred(NOP);
(gdb) disassemble 
Dump of assembler code for function main:
   0x0000555555554660 <+0>: push   rbp
   0x0000555555554661 <+1>: mov    rbp,rsp
=> 0x0000555555554664 <+4>: nop
   0x0000555555554665 <+5>: nop
   0x0000555555554666 <+6>: nop
   0x0000555555554667 <+7>: nop
   0x0000555555554668 <+8>: nop
   0x0000555555554669 <+9>: nop
   ....
   0x00005555555546c6 <+102>:   nop
   0x00005555555546c7 <+103>:   nop
   0x00005555555546c8 <+104>:   mov    eax,0x0
   0x00005555555546cd <+109>:   pop    rbp
   0x00005555555546ce <+110>:   ret    
End of assembler dump.

cmssoen2

cmssoen23#

Boost有Boost.预处理器,它可以做这件事。试试BOOST_PP_REPEAT
对于您的代码:

#include <boost/preprocessor/repetition/repeat.hpp>

#define OP(z, n, text) text
...
__asm__( BOOST_PP_REPEAT(5, OP, "noop\n"\t);

字符串

sxpgvts3

sxpgvts34#

根据Chris A的回答,这里有一个简单的方法,似乎也对我有用:

template< unsigned N > 
inline static void nops(){
    asm ("nop");
    nops< N - 1 >();
}

template<> inline void nops<0>(){};

void setup() {
  nops<10>();
}

字符串
https://godbolt.org/z/a7MMea

8qgya5xd

8qgya5xd5#

假设您正在使用GNU工具链,您可以使用gnu汇编程序ashttps://sourceware.org/binutils/docs/as/Rept.html的repeat指令

#define repeat(instruction, num) \
    asm volatile(                \
        ".rept " #num "\n\t"     \
        instruction "\n\t"       \
        ".endr\n\t");

int main() {
    repeat("nop", 5);
}

字符串
生成程序集:

push   rbp
 mov    rbp,rsp
 nop
 nop
 nop
 nop
 nop
 mov    eax,0x0
 pop    rbp
 ret


https://godbolt.org/z/j8dzYvM7c

相关问题