linux源代码情景分析---i386汇编学习

时间:2021-06-18 02:48:32
__asm__ __violate__ ("movl %1,%0" : "=r" (result) : "m" (input));

      “movl %1,%0”是指令模板;“%0”和“%1”代表指令的操作数,称为占位符,内嵌汇编靠它们将C语言表达式与指令操作数相对应。

       指令模板后面用小括号括起来的是C语言表达式,本例中只有两个:“result”和“input”,他们按照出现的顺序分别与指令操作数“%0”,“%1,”对应;第一个C表达式对应“%0”;第二个表达式对应“%1”,依次类推,操作数至多有10个,

       在每个操作数前面有一个用引号括起来的字符串,字符串的内容是对该操作数的限制或者说要求。“result”前面的限制字符串是“=r”,其中“=”表示“result”是输出操作数,“r”表示需要将“result”与某个通用寄存器相关联,先将操作数的值读入寄存器,然后在指令中使用相应寄存器,而不是“result”本身,当然指令执行完后需要将寄存器中的值存入变量“result”,从表面上看好像是指令直接对“result”进行操作,实际上GCC做了隐式处理,这样我们可以少写一些指令。“input”前面的“r”表示该表达式需要先放入某个寄存器,然后在指令中使用该寄存器参加运算。

      

限制字符
限制字符有很多种,有些是与特定体系结构相关,此处仅列出常用的限定字符和i386中可能用到的一些常用的限定符。它们的作用是指示编译器如何处理其后的C语言变量与指令操作数之间的关系,例如是将变量放在寄存器中还是放在内存中等,下表列出了常用的限定字母。

“b”将输入变量放入ebx
  “c”将输入变量放入ecx
  “d”将输入变量放入edx
  “s”将输入变量放入esi
  “d”将输入变量放入edi
  “q”将输入变量放入eax,ebx  ,ecx  ,edx中的一个
  “r”将输入变量放入通用寄存器,也就是eax ,ebx,ecx,edx,esi,edi中的一个
  “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”


操作数类型
  “=” 操作数在指令中是只写的(输出操作数)
  “+” 操作数在指令中是读写类型的(输入输出操作数)
  
   浮点数
  “f”
  浮点寄存器
  “t”第一个浮点寄存器
  “u”第二个浮点寄存器
  “G”标准的80387