这种形式的汇编语言用于Linux代码的许多部分,嵌入在汇编格式如下:



__asm__ __volatile__(



asm语句



:输出



:输入



修改:寄存器



);



asm语句是一套在ATT汇编语言的语句格式,每一行是分离的,所有的报表都包裹在一对双引号。上面使用的登记必须添加二% %前缀(%n参数N:数字);转移指令是就地转移,所以使用数字标签。



输入指定程序的输入参数,每个参数都包含在一对括号中,参数用逗号隔开。在每个参数之前,添加一个双引号括起来的标志,告诉编译器在哪里加载参数。



可用的标志是:



g让编译器决定如何加载它;



a:加载到AX / EAX;



b:加载到BX / EBX;



C:加载到CX / ECX;



D:加载到DX /能谱;



D:加载到迪/ EDI;



S:加载到硅/ ESI;



q:一,B,C,D寄存器等;



r:任何一般的登记;



I:整个立即数;



I立即数之间:0~31(用于32位移位指令);



J立即数之间:0-63(用于64位移位指令);



N:0-255,它们之间的立即数(的教学);



n:立即数,有些系统不支持的话,除了立即数的话,这些系统应该使用n不是I;;



p:有效的内存地址;



m:内存变量;



o:操作数为内存变量,但寻址方式是一个偏移量类型,这是基地址,或基于索引寻址;



V:操作数为内存变量,但寻址模式不是一个偏置式;



操作数是一个内存变量,但是寻址模式是自动递增的;



X:操作数可以是任何类型;



f:浮点数;



t:第一个浮点登记;



u:二浮点寄存器;



G:标准80387;



%:浮点常量,可以与下一个操作数交换位置。



输出;



输入输出;



在更改其值之前写一个独立的寄存器,这样函数返回值和变量不会因为同一寄存器的重复使用而出现数据覆盖。



与下一个操作数互换;



# :忽略后续字符直到逗号;



Ldquo;*;当选择寄存器的优先级时,忽略以下字符;



0~ 9:指定一个操作数,并输入和输出。通常采用g;



输出表示程序的输出位置,通常是一个变量,每个输出变量被封闭在一对圆括号中,每个输出变量用逗号隔开。向每个输出变量添加一个标志,告诉编译器输出的位置。



可用的标志是为输入参数相同,前面只有= 如= g。输出操作数必须是一个左值,且必须可写。如果一个操作数是做输出和输入,然后他们必须分开:一个操作数,一个输入操作数。一个数限制(0 ~ 9)在输入操作数的增加,表明输出操作数的数目,告诉编译器,他们必须在同一个物理位置。两个操作数可以相同或不同的词语表达。



寄存器修改告诉登记,编译器会修改。每个登记是在双引号和逗号分隔。如ax如果一个特定的硬件登记是汇编程序的引用,这些寄存器应该列在这里,以便告诉编译器,这些寄存器的值被改变了。如果汇编程序修改一些不可预知的方式,记忆memory应该添加在这里。这样,编译器不会缓存的值在登记在整个装配程序。



如:



cc:你使用的指令会改变CPU的条件登记CC;



memory:你用指令修改内存;



__volatile__是可选的,它可以防止编译器修改段汇编语句(重新排序,整理,删除,等等)。



输入参数和输出变量依次编号,第一个输出,然后输入,数字从0开始。在程序中,数字由输入参数和输出变量(添加%到前缀)表示。



输入、输出和寄存器部分不可用。如果订单不能更改,则应保留;;,除非,不引起混淆。



看一个嵌入式汇编使用ATT在C语言的一个例子。C语言中的3个int变量通常是三个内存地址,每个操作数的长度由操作系统和编译器决定。平均32位操作系统为32位,每个操作数最多为4字节。



int i=0,j=1,k=0;



__asm__ __volatile__(



PUSHL % eaxn / / asm语句



movl % 1,% eaxn / / asm语句



附加的占2,% eaxn / / asm语句



movl % eax,% 0n / /…



Popl % êx / /…



()(k)输出



g(i)、G(j)(j)输入



斧头



);



根据参数编号原则,参数k是% 0,输入参数i和j依次为% 1和% 2。值得注意的是,输出和输入标志使用g