我们先来看一个简单的内嵌汇编:
先介绍一下这段代码的内容:
“__asm__”表示后面的代码为内嵌汇编,“asm”是“__asm__”的别名。
“__volatile__”表示编译器不要优化代码,后面的指令保留原样,
“volatile”是它的别名。括号里面是汇编指令。
“movl %0,%1”是指令模板;“%0”和“%1”代表指令的操作数,称为占位符,最多十个。
注意对应关系:%0对应"=r" (a),%1对应"r" (b)。
“a”前面 的限制字符串是“=r”,其中“=”表示“a”是输出操作数,“r
”表示需要将“a”与某个通用寄存器相关联,先将操作数的值读入寄存器,然后
在指令中使用相应寄存器,而不是“a”本身,当然指令执行完后需要将寄存器中的值
存入变量“a”,从表面上看好像是指令直接对“a”进行操作,实际上GCC
做了隐式处理,这样我们可以少写一些指令。“b”前面的“r”表示该表达式需要先放入
某个寄存器,然后在指令中使用该寄存器参加运算。
所以:
表示将b读入寄存器,并且输出给a所以现在a和b都等于1.
如果我们把代码改成:
表示将a的内存地址读入寄存器,所以ab都等于a的内存地址:
指令movl
允许寄存器到寄存器,立即数到寄存器等,但是不允许内存到内存的操作,因此两个操作数
不能同时使用“m”作为限定字符。
内嵌汇编语法如下:
__asm__(
汇编语句模板:
输出部分:
输入部分:
破坏描述部分)
“=”表示他是一个输出操作数。
“r”将输入变量放入通用寄存器,也就是eax ,ebx,ecx,edx,esi,edi中的一个
“b”将输入变量放入ebx
“c”将输入变量放入ecx
“d”将输入变量放入edx
“s”将输入变量放入esi
“d”将输入变量放入edi
“q”将输入变量放入eax,ebx ,ecx ,edx中的一个
A”把eax和edx,合成一个64位的寄存器(uselong longs)
“m”内存变量
“o”操作数为内存变量,但是其寻址方式是偏移量类型,也即是基址寻址,或者是基址加变址寻址
“V”操作数为内存变量,但寻址方式不是偏移量类型
“,” 操作数为内存变量,但寻址方式为自动增量
“p”操作数是一个合法的内存地址(指针)
“g” 将输入变量放入eax,ebx,ecx ,edx中的一个或者作为内存变量
“X”操作数可以是任何类型
“I” 0-31 之间的立即数(用于32位移位指令)
“J” 0-63 之间的立即数(用于64 位移位指令)
“N” 0-255 ,之间的立即数(用于out 指令)
“i” 立即数
“n” 立即数,有些系统不支持除字以外的立即数,这些系统应该使用“n”而不是“i”
“=” 操作数在指令中是只写的(输出操作数)
“+” 操作数在指令中是读写类型的(输入输出操作数)
“t”第一个浮点寄存器
“u”第二个浮点寄存器
“G”标准的80387
//这段代码的意思是,将a读入寄存器,将b读入寄存器,相加,输出给a;