都是合法的写法。如果你将指令放在多对引号中,则除了最后一对引号之外,前面的所有引号里的最后一条指令之后都要有一个分号(;)或(n)或(nt)。比如:
__asm__("movl %eax, %ebx
stin"
"popl %edi;"
"subl %ecx, %ebx");
__asm__("movl %eax, %ebx; stint"
"popl %edi; subl %ecx, %ebx");
__asm__("movl %eax, %ebx; stint popl %edin"
"subl %ecx, %ebx");
__asm__("movl %eax, %ebx; stint popl %edi;" "subl %ecx, %ebx");
都是合法的。
上述原则可以归结为:
任意两个指令间要么被分号(;)分开,要么被放在两行; 放在两行的方法既可以从通过n的方法来实现,也可以真正的放在两行; 可以使用1对或多对引号,每1对引号里可以放任一多条指令,所有的指令都要被放到引号中。在基本内联汇编中,“Instruction List”的书写的格式和你直接在汇编文件中写非内联汇编没有什么不同,你可以在其中定义Label,定义对齐(.align n ),定义段(.section name )。例如:
__asm__(".align 2nt"
"movl %eax, %ebxnt"
"test %ebx, %ecxnt"
"jne errornt"
"stint"
"error: popl %edint"
"subl %ecx, %ebx");
上面例子的格式是Linux内联代码常用的格式,非常整齐。也建议大家都使用这种格式来写内联汇编代码。
3、__volatile__
__volatile__是GCC关键字volatile的宏定义:
#define __volatile__ volatile
__volatile__ 或volatile是可选的,你可以用它也可以不用它。如果你用了它,则是向GCC声明“不要动我所写的Instruction List,我需要原封不动的保留每一条指令”,否则当你使用了优化选项(-O)进行编译时,GCC将会根据自己的判断决定是否将这个内联汇编表达式中的指 令优化掉。
那么GCC判断的原则是什么?我不知道(如果有哪位朋友清楚的话,请告诉我)。我试验了一下,发现一条内联汇编语句如果是基本 内联汇编的话(即只有“Instruction List”,没有Input/Output/Clobber的内联汇编,我们后面将会讨论这一点),无论你是否使用__volatile__来修饰, GCC 2.96在优化编译时,都会原封不动的保留内联汇编中的“Instruction List”。但或许我的试验的例子并不充分,所以这一点并不能够得到保证。
为了保险起见,如果你不想让GCC的优化影响你的内联汇编代码,你最好在前面都加上__volatile__,而不要依赖于编译器的原则,因为即使你非常了解当前编译器的优化原则,你也无法保证这种原则将来不会发生变化。而__volatile__的含义却是恒定的。
2、带有C/C++表达式的内联汇编
GCC允许你通过C/C++表达式指定内联汇编中"Instrcuction List"中指令的输入和输出,你甚至可以不关心到底使用哪个寄存器被使用,完全靠GCC来安排和指定。这一点可以让程序员避免去考虑有限的寄存器的使用,也可以提高目标代码的效率。










