Embedded Assembly: Advanced Usages

3 parts: output, input , clobber.

From here and here:

output

  The output consists of zero, one or more output operands, separated by commas. Each operand consists of a constraint(C_expression) pair. The output operand must be constrained by the = or + modifier (described below), and, optionally, by an additional or modifier.

input

  The input consists of zero, one or more input operands, separated by commas. Each operand consists of a constraint(C_expression) pair.

clobbers

  clobbers is a comma-separated list of register names enclosed in double quotes. If an asm instruction updates registers that are not listed in the input or output of the asmstatement, the registers must be listed as clobbered registers. The following register names are valid :
r0 to r15
General purpose registers
In addition to the register names, cc and memory can also be used in the list of clobbered registers. The usage information of cc and memory is listed as follows:
cc
Add cc to the list of clobbered registers if assembler instructions can alter the condition code.
memory

Add memory to the clobber list if assembler instructions can change a memory location in an unpredictable fashion. The memory clobber ensures that the compiler does not to move the assembler instruction across other memory references and ensures that any data that is used after the completion of the assembly statement is valid.

However, the memory clobber can result in many unnecessary reloads, reducing the benefits of hardware prefetching. Thus, the memory clobber can impose a performance penalty and should be used with caution.

modifier
The modifier can be one of the following operators:
=
Indicates that the operand is write-only for this instruction. The previous value is discarded and replaced by output data. See Example 3 for detailed usage information.
+
Indicates that the operand is both read and written by the instruction. See Example 4 for detailed usage information.
&
Indicates that the operand may be modified before the instruction is finished using the input operands; a register that is used as input should not be reused here.
%
Declares the instruction to be commutative for this operand and the following operand. This means that the order of this operand and the next may be swapped when generating the instruction. This modifier can be used on an input or output operand, but cannot be specified on the last operand.
constraint
The constraint is a string literal that describes the kind of operand that is permitted, one character per constraint. The following constraints are supported:
a
Use an address register (general purpose register except r0).
d
Use a data register that is an arbitrary general purpose register. This constraint is the same as the r constraint.
g
Use a memory or immediate operand.
i
Use an immediate integer or string literal operand.
m
Use a memory operand supported by the machine. You can use this constraint for operands of the form D(R), where D is a displacement and R is a register. See Example 5 for detailed usage information.
n
Use an immediate integer.
o
Use a memory operand that is offsetable.
r
Use a general register. See Example 3 for detailed usage information.
s
Use a string literal operand.
v
Use a vector register.
0, 1, …8, 9
A matching constraint. Allocate the same register in output as in the corresponding input.
I, J, K
Integer constant values
Q, R, S, T
Memory operands. They are treated the same as constraint m.
C_expression

The C_expression is a C or C++ expression whose value is used as the operand for the asm instruction. Output operands must be modifiable lvalues. The C_expression must be consistent with the constraint specified on it. For example, if i is specified, the operand must be an integer constant number.

int main(){
   int sum = 0, one=1, two = 2; 
   __asm ("AR  %[result], %[first]\n"  
          "AR  %[result], %[second]\n"  
         :[result] "+r"(sum)
         :[first]  "r"(one), 
          [second] "r"(two) 
         );

   return sum == 3 ? 0 : 1;
}

#include <stdio.h>

int main() {

    int res = 25;
    int newRes = 55;
    asm("LR %0,%1\n" 
       :"=r"(res) 
       :"r"(newRes) 
       );
    return res;

}

#include <stdio.h>

int main() {
    int res = 25;
    asm(" AHI %0,%1\n" 
       :"+r"(res) 
       : "K"(30) 
       );
    return res;
}

 int main()
{
    int val=40, dest;
    asm(" ST %1,%0\n"
        :"=m"(dest)
        :"r"(val)
       );
    return 40 == dest ? 55 :66;
}

difference between using '+' and '=' with output oprand:

Sometimes multiple asm in one embedded asm, the output register might also be allocate as input register. So as input register, it is updated before #APP, and modified by certain asm in the multi-embedded asm. If this register shall be used as input register after that certain asm, we cannot get that pre-updated value as input register. So to avoid that circumstance, use '&' as modifier for the output register to prevent this register to be used as input register.

 

posted on 2017-12-25 17:28  三叁  阅读(262)  评论(0)    收藏  举报

导航