Microchip Technology SW006022-2 Ficha De Dados
Mixing C and Assembly Code
2012 Microchip Technology Inc.
DS52071B-page 195
_ _
asm
_ _
("add %1,%2,%0\n sl %0,%1,%0"
: "=&r"(c) : "r"(a), "r"(b));
return(c);
}
EXAMPLE 13-7:
MATCHING OPERANDS
When the assembler instruction has a read-write operand, or an operand in which only
some of the bits are to be changed, you must logically split its function into two separate
operands: one input operand and one write-only output operand. The connection
between them is expressed by constraints that say they need to be in the same location
when the instruction executes. You can use the same C expression for both operands
or different expressions. For example, here is the add instruction with bar as its
read-only source operand and foo as its read-write destination:
some of the bits are to be changed, you must logically split its function into two separate
operands: one input operand and one write-only output operand. The connection
between them is expressed by constraints that say they need to be in the same location
when the instruction executes. You can use the same C expression for both operands
or different expressions. For example, here is the add instruction with bar as its
read-only source operand and foo as its read-write destination:
asm ("add %2,%1,%0"
: "=r" (foo)
: "0" (foo), "r" (bar));
The constraint “0” for operand 1 says that it must occupy the same location as operand
0. A digit in constraint is allowed only in an input operand and must refer to an output
operand. Only a digit in the constraint can ensure that one operand will be in the same
place as another. The mere fact that foo is the value of both operands is not enough
to ensure that they will be in the same place in the generated assembler code. The
following would not work:
0. A digit in constraint is allowed only in an input operand and must refer to an output
operand. Only a digit in the constraint can ensure that one operand will be in the same
place as another. The mere fact that foo is the value of both operands is not enough
to ensure that they will be in the same place in the generated assembler code. The
following would not work:
asm ("add %2,%1,%0"
: "=r" (foo)
: "r" (foo), "r" (bar));
Various optimizations or reloading could cause operands 0 and 1 to be in different
registers. For example, the compiler might find a copy of the value of foo in one
register and use it for operand 1, but generate the output operand 0 in a different
register (copying it afterward to foo’s own address).
registers. For example, the compiler might find a copy of the value of foo in one
register and use it for operand 1, but generate the output operand 0 in a different
register (copying it afterward to foo’s own address).
EXAMPLE 13-8:
NAMING OPERANDS
It is also possible to specify input and output operands using symbolic names that can
be referenced within the assembler code template. These names are specified inside
square brackets preceding the constraint string, and can be referenced inside the
assembler code template using %[name] instead of a percentage sign followed by the
operand number. Using named operands, the above example could be coded as
follows:
be referenced within the assembler code template. These names are specified inside
square brackets preceding the constraint string, and can be referenced inside the
assembler code template using %[name] instead of a percentage sign followed by the
operand number. Using named operands, the above example could be coded as
follows:
asm ("add %[foo],%[bar],%[foo]"
: [foo] "=r" (foo)
: "0" (foo), [bar] "r" (bar));
EXAMPLE 13-9:
VOLATILE ASM STATEMENTS
You can prevent an asm instruction from being deleted, moved significantly, or
combined, by writing the keyword volatile after the asm. For example:
combined, by writing the keyword volatile after the asm. For example:
#define disi(n) \
asm volatile ("disi #%0" \
: /* no outputs */ \
: "i" (n))
In this case, the constraint letter “i” denotes an immediate operand, as required by the
disi
disi
instruction.