File: inline_asm.dox

package info (click to toggle)
avr-libc 1%3A1.6.2.cvs20080610-2
  • links: PTS
  • area: main
  • in suites: lenny
  • size: 14,848 kB
  • ctags: 55,619
  • sloc: ansic: 92,267; asm: 6,692; sh: 4,131; makefile: 2,481; python: 976; pascal: 426; perl: 116
file content (911 lines) | stat: -rw-r--r-- 29,514 bytes parent folder | download | duplicates (6)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
/* Copyright (c) 2001, 2002, Harald Kipp
   Copyright (c) 2007 Eric B. Weddington
   All rights reserved.

   Redistribution and use in source and binary forms, with or without
   modification, are permitted provided that the following conditions are met:

   * Redistributions of source code must retain the above copyright
     notice, this list of conditions and the following disclaimer.
   * Redistributions in binary form must reproduce the above copyright
     notice, this list of conditions and the following disclaimer in
     the documentation and/or other materials provided with the
     distribution.

   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
   AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
   LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
   CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
   CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   POSSIBILITY OF SUCH DAMAGE. */


/** \page inline_asm Inline Assembler Cookbook

AVR-GCC<br>
Inline Assembler Cookbook

About this Document

The GNU C compiler for Atmel AVR RISC processors offers, to embed assembly
language code into C programs. This cool feature may be used for manually
optimizing time critical parts of the software or to use specific processor
instruction, which are not available in the C language.

Because of a lack of documentation, especially for the AVR version of the
compiler, it may take some time to figure out the implementation details by
studying the compiler and assembler source code. There are also a few sample
programs available in the net. Hopefully this document will help to increase
their number.

It's assumed, that you are familiar with writing AVR assembler programs,
because this is not an AVR assembler programming tutorial. It's not a C
language tutorial either.

Note that this document does not cover file written completely in assembler
language, refer to \ref assembler for this.

Copyright (C) 2001-2002 by egnite Software GmbH

Permission is granted to copy and distribute verbatim copies of this manual
provided that the copyright notice and this permission notice are preserved on
all copies. Permission is granted to copy and distribute modified versions of
this manual provided that the entire resulting derived work is distributed
under the terms of a permission notice identical to this one.

This document describes version 3.3 of the compiler. There may be some
parts, which hadn't been completely understood by the author himself and not
all samples had been tested so far. Because the author is German and not
familiar with the English language, there are definitely some typos and syntax
errors in the text. As a programmer the author knows, that a wrong
documentation sometimes might be worse than none. Anyway, he decided to offer
his little knowledge to the public, in the hope to get enough response to
improve this document. Feel free to contact the author via e-mail. For the
latest release check http://www.ethernut.de/.

Herne, 17th of May 2002
Harald Kipp
harald.kipp-at-egnite.de

\note As of 26th of July 2002, this document has been merged into the
documentation for avr-libc. The latest version is now available at 
http://savannah.nongnu.org/projects/avr-libc/.

\section gcc_asm GCC asm Statement

Let's start with a simple example of reading a value from port D:

\code
asm("in %0, %1" : "=r" (value) : "I" (_SFR_IO_ADDR(PORTD)) );
\endcode

Each \c asm statement is devided by colons into (up to) four parts:

-# The assembler instructions, defined as a single string constant:
   \code "in %0, %1" \endcode
-# A list of output operands, separated by commas. Our example uses just one:
   \code "=r" (value) \endcode
-# A comma separated list of input operands. Again our example uses one
   operand only: \code "I" (_SFR_IO_ADDR(PORTD)) \endcode
-# Clobbered registers, left empty in our example.

You can write assembler instructions in much the same way as you would write
assembler programs. However, registers and constants are used in a different
way if they refer to expressions of your C program. The connection between
registers and C operands is specified in the second and third part of the
<tt>asm</tt> instruction, the list of input and output operands, respectively.
The general form is

\code
asm(code : output operand list : input operand list [: clobber list]);
\endcode

In the code section, operands are referenced by a percent sign followed by a
single digit. \c %0 refers to the first \c %1 to the second operand and so
forth. From the above example:

\c %0 refers to <tt>"=r" (value)</tt> and<br>
\c %1 refers to <tt>"I" (_SFR_IO_ADDR(PORTD))</tt>.

This may still look a little odd now, but the syntax of an operand list will
be explained soon. Let us first examine the part of a compiler listing which
may have been generated from our example:

\code
        lds r24,value
/* #APP */
        in r24, 12
/* #NOAPP */
        sts value,r24
\endcode

The comments have been added by the compiler to inform the assembler that the
included code was not generated by the compilation of C statements, but by
inline assembler statements. The compiler selected register \c r24 for storage
of the value read from <tt>PORTD</tt>.  The compiler could have selected any
other register, though.  It may not explicitely load or store the value and it
may even decide not to include your assembler code at all. All these decisions
are part of the compiler's optimization strategy. For example, if you never
use the variable value in the remaining part of the C program, the compiler
will most likely remove your code unless you switched off optimization. To
avoid this, you can add the volatile attribute to the \c asm statement:

\code
asm volatile("in %0, %1" : "=r" (value) : "I" (_SFR_IO_ADDR(PORTD)));
\endcode

Alternatively, operands can be given names.  The name is prepended in
brackets to the constraints in the operand list, and references to the
named operand use the bracketed name instead of a number after the %
sign.  Thus, the above example could also be written as

\code
asm("in %[retval], %[port]" :
    [retval] "=r" (value) :
    [port] "I" (_SFR_IO_ADDR(PORTD)) );
\endcode

The last part of the \c asm instruction, the clobber list, is mainly used to
tell the compiler about modifications done by the assembler code. This part
may be omitted, all other parts are required, but may be left empty. If your
assembler routine won't use any input or output operand, two colons must still
follow the assembler code string. A good example is a simple statement to
disable interrupts:

\code
asm volatile("cli"::);
\endcode

\section asm_code Assembler Code

You can use the same assembler instruction mnemonics as you'd use with any
other AVR assembler. And you can write as many assembler statements into one
code string as you like and your flash memory is able to hold.

\note The available assembler directives vary from one assembler to another.

To make it more readable, you should put each statement on a seperate line:

\code
asm volatile("nop\n\t"
             "nop\n\t"
             "nop\n\t"
             "nop\n\t"
             ::);
\endcode

The linefeed and tab characters will make the assembler listing generated by
the compiler more readable. It may look a bit odd for the first time, but
that's the way the compiler creates it's own assembler code.

You may also make use of some special registers.

<table>
  <tr>
    <td><b>Symbol</b></td>
    <td><b>Register</b></td>
  </tr>
  <tr>
    <td><tt>__SREG__</tt></td>
    <td>Status register at address 0x3F</td>
  </tr>
  <tr>
    <td><tt>__SP_H__</tt></td>
    <td>Stack pointer high byte at address 0x3E</td>
  </tr>
  <tr>
    <td><tt>__SP_L__</tt></td>
    <td>Stack pointer low byte at address 0x3D</td>
  </tr>
  <tr>
    <td><tt>__tmp_reg__</tt></td>
    <td>Register r0, used for temporary storage</td>
  </tr>
  <tr>
    <td><tt>__zero_reg__</tt></td>
    <td>Register r1, always zero</td>
  </tr>
</table>

Register \c r0 may be freely used by your assembler code and need not be
restored at the end of your code. It's a good idea to use \c __tmp_reg__ and
\c __zero_reg__ instead of \c r0 or \c r1, just in case a new compiler version
changes the register usage definitions.

\section io_ops Input and Output Operands

Each input and output operand is described by a constraint string followed by
a C expression in parantheses. <tt>AVR-GCC</tt> 3.3 knows the following
constraint characters:

\note The most up-to-date and detailed information on contraints for the avr
can be found in the gcc manual.

\note The \c x register is \c r27:r26, the \c y register is \c r29:r28, and
the \c z register is <tt>r31:r30</tt>

<table>
  <tr><td><b>Constraint</b></td><td><b>Used for</b></td><td><b>Range</b></td></tr>
  <tr><td>a</td><td>Simple upper registers</td><td>r16 to r23</td></tr>
  <tr><td>b</td><td>Base pointer registers pairs</td><td>y, z</td></tr>
  <tr><td>d</td><td>Upper register</td><td>r16 to r31</td></tr>
  <tr><td>e</td><td>Pointer register pairs</td><td>x, y, z</td></tr>
  <tr><td>q</td><td>Stack pointer register</td><td>SPH:SPL</td></tr>
  <tr><td>r</td><td>Any register</td><td>r0 to r31</td></tr>
  <tr><td>t</td><td>Temporary register</td><td>r0</td></tr>
  <tr><td>w</td><td>Special upper register pairs</td><td>r24, r26, r28, r30</td></tr>
  <tr><td>x</td><td>Pointer register pair X</td><td>x (r27:r26)</td></tr>
  <tr><td>y</td><td>Pointer register pair Y</td><td>y (r29:r28)</td></tr>
  <tr><td>z</td><td>Pointer register pair Z</td><td>z (r31:r30)</td></tr>
  <tr><td>G</td><td>Floating point constant</td><td>0.0</td></tr>
  <tr><td>I</td><td>6-bit positive integer constant</td><td>0 to 63</td></tr>
  <tr><td>J</td><td>6-bit negative integer constant</td><td>-63 to 0</td></tr>
  <tr><td>K</td><td>Integer constant</td><td>2</td></tr>
  <tr><td>L</td><td>Integer constant</td><td>0</td></tr>
  <tr><td>l</td><td>Lower registers</td><td>r0 to r15</td></tr>
  <tr><td>M</td><td>8-bit integer constant</td><td>0 to 255</td></tr>
  <tr><td>N</td><td>Integer constant</td><td>-1</td></tr>
  <tr><td>O</td><td>Integer constant</td><td>8, 16, 24</td></tr>
  <tr><td>P</td><td>Integer constant</td><td>1</td></tr>
  <tr><td>Q</td><td>(GCC >= 4.2.x) A memory address based on Y or Z pointer with displacement.</td><td>&nbsp;</td></tr>
  <tr><td>R</td><td>(GCC >= 4.3.x) Integer constant.</td><td>-6 to 5</td></tr>
</table>

The selection of
the proper contraint depends on the range of the constants or registers, which
must be acceptable to the AVR instruction they are used with. The C compiler
doesn't check any line of your assembler code. But it is able to check the
constraint against your C expression. However, if you specify the wrong
constraints, then the compiler may silently pass wrong code to the assembler.
And, of course, the assembler will fail with some cryptic output or internal
errors. For example, if you specify the constraint \c "r" and you are using
this register with an \c "ori" instruction in your assembler code, then the
compiler may select any register. This will fail, if the compiler chooses
<tt>r2</tt> to \c r15. (It will never choose \c r0 or \c r1, because these are
uses for special purposes.) That's why the correct constraint in that case is
<tt>"d"</tt>. On the other hand, if you use the constraint <tt>"M"</tt>, the
compiler will make sure that you don't pass anything else but an 8-bit value.
Later on we will see how to pass multibyte expression results to the
assembler code.

The following table shows all AVR assembler mnemonics which require operands,
and the related contraints. Because of the improper constraint definitions in
version 3.3, they aren't strict enough. There is, for example, no
constraint, which restricts integer constants to the range 0 to 7 for bit set
and bit clear operations.

<table>
  <tr>
    <td><b>Mnemonic</b></td>
    <td><b>Constraints</b></td>
    <td> </td>
    <td><b>Mnemonic</b></td>
    <td><b>Constraints</b></td>
  </tr>
  <tr>
    <td>adc</td>
    <td>r,r</td>
    <td> </td>
    <td>add</td>
    <td>r,r</td>
  </tr>
  <tr>
    <td>adiw</td>
    <td>w,I</TD>
    <td> </td>
    <td>and</td>
    <td>r,r</td>
  </tr>
  <tr>
    <td>andi</td>
    <td>d,M</TD>
    <td> </td>
    <td>asr</td>
    <td>r</td>
  </tr>
  <tr>
    <td>bclr</td>
    <td>I</TD>
    <td> </td>
    <td>bld</td>
    <td>r,I</TD>
  </tr>
  <tr>
    <td>brbc</td>
    <td>I,label</td>
    <td> </td>
    <td>brbs</td>
    <td>I,label</td>
  </tr>
  <tr>
    <td>bset</td>
    <td>I</TD>
    <td> </td>
    <td>bst</td>
    <td>r,I</TD>
  </tr>
  <tr>
    <td>cbi</td>
    <td>I,I</TD>
    <td> </td>
    <td>cbr</td>
    <td>d,I</TD>
  </tr>
  <tr>
    <td>com</td>
    <td>r</td>
    <td> </td>
    <td>cp</td>
    <td>r,r</td>
  </tr>
  <tr>
    <td>cpc</td>
    <td>r,r</td>
    <td> </td>
    <td>cpi</td>
    <td>d,M</TD>
  </tr>
  <tr>
    <td>cpse</td>
    <td>r,r</td>
    <td> </td>
    <td>dec</td>
    <td>r</td>
  </tr>
  <tr>
    <td>elpm</td>
    <td>t,z</td>
    <td> </td>
    <td>eor</td>
    <td>r,r</td>
  </tr>
  <tr>
    <td>in</td>
    <td>r,I</TD>
    <td> </td>
    <td>inc</td>
    <td>r</td>
  </tr>
  <tr>
    <td>ld</td>
    <td>r,e</td>
    <td> </td>
    <td>ldd</td>
    <td>r,b</td>
  </tr>
  <tr>
    <td>ldi</td>
    <td>d,M</TD>
    <td> </td>
    <td>lds</td>
    <td>r,label</td>
  </tr>
  <tr>
    <td>lpm</td>
    <td>t,z</td>
    <td> </td>
    <td>lsl</td>
    <td>r</td>
  </tr>
  <tr>
    <td>lsr</td>
    <td>r</td>
    <td> </td>
    <td>mov</td>
    <td>r,r</td>
  </tr>
  <tr>
    <td>movw</td>
    <td>r,r</td>
    <td> </td>
    <td>mul</td>
    <td>r,r</td>
  </tr>
  <tr>
    <td>neg</td>
    <td>r</td>
    <td> </td>
    <td>or</td>
    <td>r,r</td>
  </tr>
  <tr>
    <td>ori</td>
    <td>d,M</TD>
    <td> </td>
    <td>out</td>
    <td>I,r</td>
  </tr>
  <tr>
    <td>pop</td>
    <td>r</td>
    <td> </td>
    <td>push</td>
    <td>r</td>
  </tr>
  <tr>
    <td>rol</td>
    <td>r</td>
    <td> </td>
    <td>ror</td>
    <td>r</td>
  </tr>
  <tr>
    <td>sbc</td>
    <td>r,r</td>
    <td> </td>
    <td>sbci</td>
    <td>d,M</TD>
  </tr>
  <tr>
    <td>sbi</td>
    <td>I,I</TD>
    <td> </td>
    <td>sbic</td>
    <td>I,I</TD>
  </tr>
  <tr>
    <td>sbiw</td>
    <td>w,I</TD>
    <td> </td>
    <td>sbr</td>
    <td>d,M</TD>
  </tr>
  <tr>
    <td>sbrc</td>
    <td>r,I</TD>
    <td> </td>
    <td>sbrs</td>
    <td>r,I</TD>
  </tr>
  <tr>
    <td>ser</td>
    <td>d</td>
    <td> </td>
    <td>st</td>
    <td>e,r</td>
  </tr>
  <tr>
    <td>std</td>
    <td>b,r</td>
    <td> </td>
    <td>sts</td>
    <td>label,r</td>
  </tr>
  <tr>
    <td>sub</td>
    <td>r,r</td>
    <td> </td>
    <td>subi</td>
    <td>d,M</TD>
  </tr>
  <tr>
    <td>swap</td>
    <td>r</td>
    <td> </td>
    <td> </td>
    <td> </td>
  </tr>
</table>

Constraint characters may be prepended by a single constraint modifier.
Contraints without a modifier specify read-only operands. Modifiers are:

<table>
  <tr>
    <td><b>Modifier</b></td>
    <td><b>Specifies</b></td>
  </tr>
  <tr>
    <td>=</td>
    <td>Write-only operand, usually used for all output operands.</td>
  </tr>
  <tr>
    <td>+</td>
    <td>Read-write operand</td>
  </tr>
  <tr>
    <td>&</td>
    <td>Register should be used for output only</td>
  </tr>
</table>

Output operands must be write-only and the C expression result must be an
lvalue, which means that the operands must be valid on the left side of
assignments.  Note, that the compiler will not check if the operands are of
reasonable type for the kind of operation used in the assembler instructions.

Input operands are, you guessed it, read-only. But what if you need the same
operand for input and output? As stated above, read-write operands are not
supported in inline assembler code. But there is another solution. For input
operators it is possible to use a single digit in the constraint string. Using
digit n tells the compiler to use the same register as for the n-th operand,
starting with zero. Here is an example:

\code
asm volatile("swap %0" : "=r" (value) : "0" (value));
\endcode

This statement will swap the nibbles of an 8-bit variable named value.
Constraint \c "0" tells the compiler, to use the same input register as for
the first operand. Note however, that this doesn't automatically imply the
reverse case. The compiler may choose the same registers for input and output,
even if not told to do so. This is not a problem in most cases, but may be
fatal if the output operator is modified by the assembler code before the
input operator is used. In the situation where your code depends on different
registers used for input and output operands, you must add the \c & constraint
modifier to your output operand. The following example demonstrates this
problem:

\code
asm volatile("in %0,%1"    "\n\t"
             "out %1, %2"  "\n\t" 
             : "=&r" (input) 
             : "I" (_SFR_IO_ADDR(port)), "r" (output)
            );
\endcode

In this example an input value is read from a port and then an output value is
written to the same port. If the compiler would have choosen the same register
for input and output, then the output value would have been destroyed on the
first assembler instruction. Fortunately, this example uses the \c &
constraint modifier to instruct the compiler not to select any register for
the output value, which is used for any of the input operands.  Back to
swapping. Here is the code to swap high and low byte of a 16-bit value:

\code
asm volatile("mov __tmp_reg__, %A0" "\n\t"
             "mov %A0, %B0"         "\n\t"
             "mov %B0, __tmp_reg__" "\n\t"
             : "=r" (value)
             : "0" (value)
            );
\endcode

First you will notice the usage of register <tt>__tmp_reg__</tt>, which we
listed among other special registers in the \ref asm_code section. You can use
this register without saving its contents. Completely new are those letters
<tt>A</tt> and \c B in <tt>\%A0</tt> and <tt>\%B0</tt>. In fact they refer to
two different 8-bit registers, both containing a part of value.

Another example to swap bytes of a 32-bit value:

\code
asm volatile("mov __tmp_reg__, %A0" "\n\t"
             "mov %A0, %D0"         "\n\t"
             "mov %D0, __tmp_reg__" "\n\t"
             "mov __tmp_reg__, %B0" "\n\t"
             "mov %B0, %C0"         "\n\t"
             "mov %C0, __tmp_reg__" "\n\t"
             : "=r" (value)
             : "0" (value)
            );
\endcode

Instead of listing the same operand as both, input and output operand,
it can also be declared as a read-write operand.  This must be applied
to an output operand, and the respective input operand list remains
empty:

\code
asm volatile("mov __tmp_reg__, %A0" "\n\t"
             "mov %A0, %D0"         "\n\t"
             "mov %D0, __tmp_reg__" "\n\t"
             "mov __tmp_reg__, %B0" "\n\t"
             "mov %B0, %C0"         "\n\t"
             "mov %C0, __tmp_reg__" "\n\t"
             : "+r" (value));
\endcode

If operands do not fit into a single register, the compiler will automatically
assign enough registers to hold the entire operand. In the assembler code you
use <tt>\%A0</tt> to refer to the lowest byte of the first operand,
<tt>\%A1</tt> to the lowest byte of the second operand and so on. The next
byte of the first operand will be <tt>\%B0</tt>, the next byte <tt>\%C0</tt>
and so on.

This also implies, that it is often neccessary to cast the type of an input
operand to the desired size.

A final problem may arise while using pointer register pairs. If you define an
input operand

\code
"e" (ptr)
\endcode

and the compiler selects register \c Z \c (r30:r31), then 

<tt>\%A0</tt> refers to \c r30 and<br>
<tt>\%B0</tt> refers to \c r31.

But both versions will fail during the assembly stage of the compiler, if you
explicitely need \c Z, like in

\code
ld r24,Z
\endcode

If you write

\code
ld r24, %a0
\endcode

with a lower case \c a following the percent sign, then the compiler will
create the proper assembler line.

\section clobbers Clobbers

As stated previously, the last part of the \c asm statement, the list of
clobbers, may be omitted, including the colon seperator. However, if you are
using registers, which had not been passed as operands, you need to inform the
compiler about this. The following example will do an atomic increment. It
increments an 8-bit value pointed to by a pointer variable in one go, without
being interrupted by an interrupt routine or another thread in a multithreaded
environment. Note, that we must use a pointer, because the incremented value
needs to be stored before interrupts are enabled.

\code
asm volatile(
    "cli"               "\n\t"
    "ld r24, %a0"       "\n\t"
    "inc r24"           "\n\t"
    "st %a0, r24"       "\n\t"
    "sei"               "\n\t"
    :
    : "e" (ptr)
    : "r24"
);
\endcode

The compiler might produce the following code:

\code
    cli
    ld r24, Z
    inc r24
    st Z, r24
    sei
\endcode

One easy solution to avoid clobbering register \c r24 is, to make use of the
special temporary register \c __tmp_reg__ defined by the compiler.

\code
asm volatile(
    "cli"                       "\n\t"
    "ld __tmp_reg__, %a0"       "\n\t"
    "inc __tmp_reg__"           "\n\t"
    "st %a0, __tmp_reg__"       "\n\t"
    "sei"                       "\n\t"
    :
    : "e" (ptr)
);
\endcode

The compiler is prepared to reload this register next time it uses it. Another
problem with the above code is, that it should not be called in code sections,
where interrupts are disabled and should be kept disabled, because it will
enable interrupts at the end. We may store the current status, but then we
need another register. Again we can solve this without clobbering a fixed, but
let the compiler select it. This could be done with the help of a local C
variable.

\code
{
    uint8_t s;
    asm volatile(
        "in %0, __SREG__"           "\n\t"
        "cli"                       "\n\t"
        "ld __tmp_reg__, %a1"       "\n\t"
        "inc __tmp_reg__"           "\n\t"
        "st %a1, __tmp_reg__"       "\n\t"
        "out __SREG__, %0"          "\n\t"
        : "=&r" (s)
        : "e" (ptr)
    );
}
\endcode

Now every thing seems correct, but it isn't really. The assembler code
modifies the variable, that \c ptr points to. The compiler will not recognize
this and may keep its value in any of the other registers. Not only does the
compiler work with the wrong value, but the assembler code does too.  The C
program may have modified the value too, but the compiler didn't update the
memory location for optimization reasons. The worst thing you can do in this
case is:

\code
{
    uint8_t s;
    asm volatile(
        "in %0, __SREG__"           "\n\t"
        "cli"                       "\n\t"
        "ld __tmp_reg__, %a1"       "\n\t"
        "inc __tmp_reg__"           "\n\t"
        "st %a1, __tmp_reg__"       "\n\t"
        "out __SREG__, %0"          "\n\t"
        : "=&r" (s)
        : "e" (ptr)
        : "memory"
    );
}
\endcode

The special clobber "memory" informs the compiler that the assembler code may
modify any memory location. It forces the compiler to update all variables for
which the contents are currently held in a register before executing the
assembler code. And of course, everything has to be reloaded again after this
code.

In most situations, a much better solution would be to declare the pointer
destination itself volatile:

\code
volatile uint8_t *ptr;
\endcode

This way, the compiler expects the value pointed to by \c ptr to be changed
and will load it whenever used and store it whenever modified.

Situations in which you need clobbers are very rare. In most cases there will
be better ways. Clobbered registers will force the compiler to store their
values before and reload them after your assembler code. Avoiding clobbers
gives the compiler more freedom while optimizing your code.

\section asm_macros Assembler Macros

In order to reuse your assembler language parts, it is useful to define them
as macros and put them into include files. AVR Libc comes with a bunch of
them, which could be found in the directory \c avr/include. Using such include
files may produce compiler warnings, if they are used in modules, which are
compiled in strict ANSI mode. To avoid that, you can write \c __asm__ instead
of \c asm and \c __volatile__ instead of \c volatile. These are equivalent
aliases.

Another problem with reused macros arises if you are using labels. In such
cases you may make use of the special pattern \c %=, which is replaced by a
unique number on each \c asm statement. The following code had been taken from
<tt>avr/include/iomacros.h</tt>:


\verbatim#define loop_until_bit_is_clear(port,bit)  \
        __asm__ __volatile__ (             \
        "L_%=: " "sbic %0, %1" "\n\t"      \
                 "rjmp L_%="               \
                 : /* no outputs */        \
                 : "I" (_SFR_IO_ADDR(port)),  \
                   "I" (bit)    \
        )
\endverbatim

When used for the first time, \c L_%= may be translated to \c L_1404, the next
usage might create \c L_1405 or whatever. In any case, the labels became unique
too.

Another option is to use Unix-assembler style numeric labels.  They are
explained in \ref faq_asmstabs.  The above example would then look like:

\verbatim#define loop_until_bit_is_clear(port,bit)  \
        __asm__ __volatile__ (             \
        "1: " "sbic %0, %1" "\n\t"      \
                 "rjmp 1b"               \
                 : /* no outputs */        \
                 : "I" (_SFR_IO_ADDR(port)),  \
                   "I" (bit)    \
        )
\endverbatim


\section asm_c_stubs C Stub Functions

Macro definitions will include the same assembler code whenever they are
referenced. This may not be acceptable for larger routines. In this case you
may define a C stub function, containing nothing other than your assembler
code.

\code
void delay(uint8_t ms)
{
    uint16_t cnt;
    asm volatile (
        "\n"
        "L_dl1%=:" "\n\t"
        "mov %A0, %A2" "\n\t"
        "mov %B0, %B2" "\n"
        "L_dl2%=:" "\n\t"
        "sbiw %A0, 1" "\n\t"
        "brne L_dl2%=" "\n\t"
        "dec %1" "\n\t"
        "brne L_dl1%=" "\n\t"
        : "=&w" (cnt)
        : "r" (ms), "r" (delay_count)
        );
}
\endcode

The purpose of this function is to delay the program execution by a specified
number of milliseconds using a counting loop. The global 16 bit variable
delay_count must contain the CPU clock frequency in Hertz divided by 4000 and
must have been set before calling this routine for the first time.  As
described in the \ref clobbers "clobber" section, the routine uses a local
variable to hold a temporary value.

Another use for a local variable is a return value. The following function
returns a 16 bit value read from two successive port addresses.

\code
uint16_t inw(uint8_t port)
{
    uint16_t result;
    asm volatile (
        "in %A0,%1" "\n\t"
        "in %B0,(%1) + 1"
        : "=r" (result)
        : "I" (_SFR_IO_ADDR(port))
        );
    return result;
}
\endcode

\note inw() is supplied by avr-libc.

\section c_names_in_asm C Names Used in Assembler Code

By default \c AVR-GCC uses the same symbolic names of functions or variables
in C and assembler code. You can specify a different name for the assembler
code by using a special form of the \c asm statement:

\code
unsigned long value asm("clock") = 3686400;
\endcode

This statement instructs the compiler to use the symbol name clock rather than
value. This makes sense only for external or static variables, because local
variables do not have symbolic names in the assembler code. However, local
variables may be held in registers.

With \c AVR-GCC you can specify the use of a specific register:

\code
void Count(void)
{
    register unsigned char counter asm("r3");

    ... some code...
    asm volatile("clr r3");
    ... more code...
}
\endcode

The assembler instruction, <tt>"clr r3"</tt>, will clear the variable counter.
\c AVR-GCC will not completely reserve the specified register. If the
optimizer recognizes that the variable will not be referenced any longer, the
register may be re-used. But the compiler is not able to check wether this
register usage conflicts with any predefined register. If you reserve too many
registers in this way, the compiler may even run out of registers during code
generation.

In order to change the name of a function, you need a prototype declaration,
because the compiler will not accept the \c asm keyword in the function
definition:

\code
extern long Calc(void) asm ("CALCULATE");
\endcode

Calling the function \c Calc() will create assembler instructions to call the
function \c CALCULATE.

\section links Links

For a more thorough discussion of inline assembly usage, see the gcc user
manual. The latest version of the gcc manual is always available here:
http://gcc.gnu.org/onlinedocs/

*/