📄 extended-asm.html
字号:
assembler dialects use semicolons to start a comment. The input operands are guaranteed not to use any of the clobberedregisters, and neither will the output operands' addresses, so you canread and write the clobbered registers as many times as you like. Hereis an example of multiple instructions in a template; it assumes thesubroutine <code>_foo</code> accepts arguments in registers 9 and 10:<pre class="smallexample"> asm ("movl %0,r9\n\tmovl %1,r10\n\tcall _foo" : /* no outputs */ : "g" (from), "g" (to) : "r9", "r10"); </pre> <p>Unless an output operand has the <code>&</code> constraint modifier, GCCmay allocate it in the same register as an unrelated input operand, onthe assumption the inputs are consumed before the outputs are produced. This assumption may be false if the assembler code actually consists ofmore than one instruction. In such a case, use <code>&</code> for each outputoperand that may not overlap an input. See <a href="Modifiers.html#Modifiers">Modifiers</a>. <p>If you want to test the condition code produced by an assemblerinstruction, you must include a branch and a label in the <code>asm</code>construct, as follows:<pre class="smallexample"> asm ("clr %0\n\tfrob %1\n\tbeq 0f\n\tmov #1,%0\n0:" : "g" (result) : "g" (input)); </pre><p>This assumes your assembler supports local labels, as the GNU assemblerand most Unix assemblers do. <p>Speaking of labels, jumps from one <code>asm</code> to another are notsupported. The compiler's optimizers do not know about these jumps, andtherefore they cannot take account of them when deciding how tooptimize. <p>Usually the most convenient way to use these <code>asm</code> instructions is toencapsulate them in macros that look like functions. For example,<pre class="smallexample"> #define sin(x) \ ({ double __value, __arg = (x); \ asm ("fsinx %1,%0": "=f" (__value): "f" (__arg)); \ __value; }) </pre><p>Here the variable <code>__arg</code> is used to make sure that the instructionoperates on a proper <code>double</code> value, and to accept only thosearguments <code>x</code> which can convert automatically to a <code>double</code>. <p>Another way to make sure the instruction operates on the correct datatype is to use a cast in the <code>asm</code>. This is different from using avariable <code>__arg</code> in that it converts more different types. Forexample, if the desired type were <code>int</code>, casting the argument to<code>int</code> would accept a pointer with no complaint, while assigning theargument to an <code>int</code> variable named <code>__arg</code> would warn aboutusing a pointer unless the caller explicitly casts it. <p>If an <code>asm</code> has output operands, GCC assumes for optimizationpurposes the instruction has no side effects except to change the outputoperands. This does not mean instructions with a side effect cannot beused, but you must be careful, because the compiler may eliminate themif the output operands aren't used, or move them out of loops, orreplace two with one if they constitute a common subexpression. Also,if your instruction does have a side effect on a variable that otherwiseappears not to change, the old value of the variable may be reused laterif it happens to be found in a register. <p>You can prevent an <code>asm</code> instruction from being deleted, movedsignificantly, or combined, by writing the keyword <code>volatile</code> afterthe <code>asm</code>. For example:<pre class="smallexample"> #define get_and_set_priority(new) \ ({ int __old; \ asm volatile ("get_and_set_priority %0, %1" \ : "=g" (__old) : "g" (new)); \ __old; }) </pre><p>If you write an <code>asm</code> instruction with no outputs, GCC will knowthe instruction has side-effects and will not delete the instruction ormove it outside of loops. <p>The <code>volatile</code> keyword indicates that the instruction hasimportant side-effects. GCC will not delete a volatile <code>asm</code> ifit is reachable. (The instruction can still be deleted if GCC canprove that control-flow will never reach the location of theinstruction.) In addition, GCC will not reschedule instructionsacross a volatile <code>asm</code> instruction. For example:<pre class="smallexample"> *(volatile int *)addr = foo; asm volatile ("eieio" : : ); </pre><p>Assume <code>addr</code> contains the address of a memory mapped deviceregister. The PowerPC <code>eieio</code> instruction (Enforce In-orderExecution of I/O) tells the CPU to make sure that the store to thatdevice register happens before it issues any other I/O. <p>Note that even a volatile <code>asm</code> instruction can be moved in waysthat appear insignificant to the compiler, such as across jumpinstructions. You can't expect a sequence of volatile <code>asm</code>instructions to remain perfectly consecutive. If you want consecutiveoutput, use a single <code>asm</code>. Also, GCC will perform someoptimizations across a volatile <code>asm</code> instruction; GCC does not"forget everything" when it encounters a volatile <code>asm</code>instruction the way some other compilers do. <p>An <code>asm</code> instruction without any operands or clobbers (an "oldstyle" <code>asm</code>) will be treated identically to a volatile<code>asm</code> instruction. <p>It is a natural idea to look for a way to give access to the conditioncode left by the assembler instruction. However, when we attempted toimplement this, we found no way to make it work reliably. The problemis that output operands might need reloading, which would result inadditional following "store" instructions. On most machines, theseinstructions would alter the condition code before there was time totest it. This problem doesn't arise for ordinary "test" and"compare" instructions because they don't have any output operands. <p>For reasons similar to those described above, it is not possible to givean assembler instruction access to the condition code left by previousinstructions. <p>If you are writing a header file that should be includable in ISO Cprograms, write <code>__asm__</code> instead of <code>asm</code>. See <a href="Alternate-Keywords.html#Alternate%20Keywords">Alternate Keywords</a>.<h3 class="subsection">Size of an <code>asm</code></h4><p>Some targets require that GCC track the size of each instruction used inorder to generate correct code. Because the final length of an<code>asm</code> is only known by the assembler, GCC must make an estimate asto how big it will be. The estimate is formed by counting the number ofstatements in the pattern of the <code>asm</code> and multiplying that by thelength of the longest instruction on that processor. Statements in the<code>asm</code> are identified by newline characters and whatever statementseparator characters are supported by the assembler; on most processorsthis is the `<code>;</code>' character. <p>Normally, GCC's estimate is perfectly adequate to ensure that correctcode is generated, but it is possible to confuse the compiler if you usepseudo instructions or assembler macros that expand into multiple realinstructions or if you use assembler directives that expand to morespace in the object file than would be needed for a single instruction. If this happens then the assembler will produce a diagnostic saying thata label is unreachable.<h3 class="subsection">i386 floating point asm operands</h4><p>There are several rules on the usage of stack-like regs inasm_operands insns. These rules apply only to the operands that arestack-like regs: <ol type=1 start=1><li>Given a set of input regs that die in an asm_operands, it isnecessary to know which are implicitly popped by the asm, andwhich must be explicitly popped by gcc. <p>An input reg that is implicitly popped by the asm must beexplicitly clobbered, unless it is constrained to match anoutput operand. </p><li>For any input reg that is implicitly popped by an asm, it isnecessary to know how to adjust the stack to compensate for the pop. If any non-popped input is closer to the top of the reg-stack thanthe implicitly popped reg, it would not be possible to know what thestack looked like--it's not clear how the rest of the stack "slidesup". <p>All implicitly popped input regs must be closer to the top ofthe reg-stack than any input that is not implicitly popped. <p>It is possible that if an input dies in an insn, reload mightuse the input reg for an output reload. Consider this example: <pre class="smallexample"> asm ("foo" : "=t" (a) : "f" (b)); </pre> <p>This asm says that input B is not popped by the asm, and thatthe asm pushes a result onto the reg-stack, i.e., the stack is onedeeper after the asm than it was before. But, it is possible thatreload will think that it can use the same reg for both the input andthe output, if input B dies in this insn. <p>If any input operand uses the <code>f</code> constraint, all output regconstraints must use the <code>&</code> earlyclobber. <p>The asm above would be written as <pre class="smallexample"> asm ("foo" : "=&t" (a) : "f" (b)); </pre> </p><li>Some operands need to be in particular places on the stack. Alloutput operands fall in this category--there is no other way toknow which regs the outputs appear in unless the user indicatesthis in the constraints. <p>Output operands must specifically indicate which reg an outputappears in after an asm. <code>=f</code> is not allowed: the operandconstraints must select a class with a single reg. </p><li>Output operands may not be "inserted" between existing stack regs. Since no 387 opcode uses a read/write operand, all output operandsare dead before the asm_operands, and are pushed by the asm_operands. It makes no sense to push anywhere but the top of the reg-stack. <p>Output operands must start at the top of the reg-stack: outputoperands may not "skip" a reg. </p><li>Some asm statements may need extra stack space for internalcalculations. This can be guaranteed by clobbering stack registersunrelated to the inputs and outputs. </ol> <p>Here are a couple of reasonable asms to want to write. This asmtakes one input, which is internally popped, and produces two outputs.<pre class="smallexample"> asm ("fsincos" : "=t" (cos), "=u" (sin) : "0" (inp)); </pre> <p>This asm takes two inputs, which are popped by the <code>fyl2xp1</code> opcode,and replaces them with one output. The user must code the <code>st(1)</code>clobber for reg-stack.c to know that <code>fyl2xp1</code> pops both inputs.<pre class="smallexample"> asm ("fyl2xp1" : "=t" (result) : "0" (x), "u" (y) : "st(1)"); </pre> </body></html>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -