{"id":264,"date":"2013-11-08T17:27:48","date_gmt":"2013-11-08T15:27:48","guid":{"rendered":"https:\/\/blog.ramses-pyramidenbau.de\/?p=264"},"modified":"2013-11-08T17:27:48","modified_gmt":"2013-11-08T15:27:48","slug":"self-expanding-loops-in-c","status":"publish","type":"post","link":"https:\/\/blog.vmexit.de\/?p=264","title":{"rendered":"Self Expanding Loops in C"},"content":{"rendered":"<p>Imagine you want to define a C preprocessor statement like this:<\/p>\n<pre class=\"brush: cpp; light: true; title: ; notranslate\" title=\"\">#define NUM_NOPS(i) .....<\/pre>\n<p>and later on, in your code:<\/p>\n<pre class=\"brush: cpp; light: true; title: ; notranslate\" title=\"\">NUM_NOPS(5);<\/pre>\n<p>and you want your preprocessor to roll out the following code:<\/p>\n<pre class=\"brush: cpp; light: true; title: ; notranslate\" title=\"\">\r\nasm volatile(&quot;nop&quot;);\r\nasm volatile(&quot;nop&quot;);\r\nasm volatile(&quot;nop&quot;);\r\nasm volatile(&quot;nop&quot;);\r\nasm volatile(&quot;nop&quot;);\r\n<\/pre>\n<p>This is not as easy as it looks like. One possibility is to use Boost&#8217;s Preprocessor Repetition Utility: <em>&lt;boost\/preprocessor\/repetition\/repeat.hpp&gt;<\/em>. But however, let&#8217;s assume you don&#8217;t want to use any third party libraries. There is one further possibility. You can use GCC&#8217;s unrool loops functionality:<\/p>\n<pre class=\"brush: cpp; light: true; title: ; notranslate\" title=\"\">\r\n#pragma GCC push_options\r\n#pragma GCC optimize (&quot;unroll-loops&quot;)\r\n#pragma GCC optimize (&quot;O2&quot;)\r\nvoid nops() {\r\n int i = 0;\r\n for(; i &lt; 10 ; i++) {\r\n   asm volatile(&quot;nop&quot;);\r\n }\r\n}\r\n#pragma GCC pop_options\r\n\r\nint main(void) {\r\n  nops();\r\n}\r\n<\/pre>\n<p>You should compile it with:<\/p>\n<p>    gcc -c -o test.o -O3 test.c <\/p>\n<p>Having a look at the disassembly proves, that your loop was rolled out:<\/p>\n<pre class=\"brush: cpp; light: true; title: ; notranslate\" title=\"\">\r\nobjdump -d test.o\r\n\r\ntest.o:     file format elf64-x86-64\r\n\r\n\r\nDisassembly of section .text:\r\n\r\n0000000000000000 &lt;nops&gt;:\r\n   0:   90                      nop\r\n   1:   90                      nop\r\n   2:   90                      nop\r\n   3:   90                      nop\r\n   4:   90                      nop\r\n   5:   90                      nop\r\n   6:   90                      nop\r\n   7:   90                      nop\r\n   8:   90                      nop\r\n   9:   90                      nop\r\n   a:   c3                      retq   \r\n\r\nDisassembly of section .text.startup:\r\n\r\n0000000000000000 &lt;main&gt;:\r\n   0:   31 c0                   xor    %eax,%eax\r\n   2:   e8 00 00 00 00          callq  7 &lt;main+0x7&gt;\r\n   7:   f3 c3                   repz retq \r\n<\/pre>\n","protected":false},"excerpt":{"rendered":"<p>Imagine you want to define a C preprocessor statement like this: #define NUM_NOPS(i) &#8230;.. and later on, in your code: NUM_NOPS(5); and you want your preprocessor to roll out the following code: asm volatile(&quot;nop&quot;); asm volatile(&quot;nop&quot;); asm volatile(&quot;nop&quot;); asm volatile(&quot;nop&quot;); asm volatile(&quot;nop&quot;); This is not as easy as it looks like. One possibility is to &hellip; <a href=\"https:\/\/blog.vmexit.de\/?p=264\" class=\"more-link\">Continue reading <span class=\"screen-reader-text\">Self Expanding Loops in C<\/span> <span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[5],"tags":[],"class_list":["post-264","post","type-post","status-publish","format-standard","hentry","category-c"],"_links":{"self":[{"href":"https:\/\/blog.vmexit.de\/index.php?rest_route=\/wp\/v2\/posts\/264","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/blog.vmexit.de\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blog.vmexit.de\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blog.vmexit.de\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/blog.vmexit.de\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=264"}],"version-history":[{"count":7,"href":"https:\/\/blog.vmexit.de\/index.php?rest_route=\/wp\/v2\/posts\/264\/revisions"}],"predecessor-version":[{"id":271,"href":"https:\/\/blog.vmexit.de\/index.php?rest_route=\/wp\/v2\/posts\/264\/revisions\/271"}],"wp:attachment":[{"href":"https:\/\/blog.vmexit.de\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=264"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.vmexit.de\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=264"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.vmexit.de\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=264"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}