浅谈GNU 嵌入式汇编具体因使用方法

        在/linux0.11/kernel/trap.c文件中,第一次接触到C语言中的嵌入式汇编代码。详细的使用说明可以参考GNUgcc手册中第4章的内容或者参考文献《using assembly with gcc》。

  具有输入和输出参数的嵌入式汇编的基本格式为:

  asm(“汇编语句“

  asm(”汇编语句“

  : 输出寄存器

  : 输入寄存器

  : 会被修改的寄存器);

  其中,”汇编语句“是你写汇编指令的地方;”输出寄存器“表示当这段嵌入汇编执行完之后,哪些寄存器用于存放输出数据。”输入寄存器“表示在执行汇编代码时,这里指定的一些寄存器中应该存放的输入值,他们分别对应着一C变量或者常数值。下面将举例说明嵌入式汇编的具体因使用方法。

  例如1:

浅谈GNU 嵌入式汇编具体因使用方法

  这段代码定义了1个嵌入式汇编函数。因为是宏语句,需要在一行上定义,因此这里使用反斜行‘\’将这些语句连成1行。第1行定义了宏的名称,即宏函数名称为get_seg_byte(seg,addr)。第3行定义了一个寄存器变量_reg 。 第4行上的_asm_表示嵌入汇编语句开始。从第4行到第7行的4条AT&T 格式的汇编语句。

  第8行是输出寄存器,这句话的含义是在这段代码运行结束后将eax所代表的寄存器中的值放入_res 变量中,作为本函数的输出值。为了在上面汇编语句中使用该地址值,嵌入汇编程序规定把输入和输出寄存器统一按顺序编号,顺序是从输出寄存器序列从左到右从上到下以%0 开始,分别记为%0,%1,%2.。。.%9。因此,输出寄存器编号为%0 输入寄存器前一部分“”(seg)的编号为%1,而后一部分的编号为%2. 上面第6行上的%2代表(*(addr))这个内存偏移量。

  现在分析4-7行上代码的具体作用。第1句将fs段寄存器的内容入栈;第2句将eax中的段值赋给fs段寄存器;第3句是把fs:(*addr))所制定的字节放入al寄存器。当执行完汇编语句后,输出寄存器eax的值将被放入_res。

  经过上面的分析,我们知道宏名称中的seg代表一指定的内存段值,而addr表示一内存偏移地址量。到现在为止,我们应该很清楚这段程序的功能。该宏函数是从指定的段和偏移量的内存地址处取一个字节。

  例如2:

浅谈GNU 嵌入式汇编具体因使用方法

  1-3行这三句是常用的汇编语句,用以清方向标识位,城府保存值。第四行说明没有用到输出寄存器。第5行的含义是将count-1的值将在到ecx寄存器中(加载码是“c“)fill_value 加载到eax中,dest放到edi中。 为什们要让gcc编译程序去做这样的加载,而不让我们自己做呢?因为gcc在它进行寄存器分配时可以进行某些优化工作。例如fill_value值可能已经加载到eax中。如果在一个循环语句中的话,gcc可能在整个循环操作中保存eax,这样就可以在每次循环中少用1个movl语句。

  最后1行是告诉gcc这些寄存器中的值已经改变了。很奇怪吧?不过,gcc知道你拿这些寄存器做了什么后,这确实能够对gcc的优化操作有所帮助。

  下面是可能会用的寄存器加载码及其具体含义:

  代码 说明

  a 使用寄存器eax

  b 使用寄存器ebx

  c 使用寄存器ecx

  d 使用寄存器edx

  S 使用寄存器esi

  D 使用寄存器edi

  q 使用动态分配字节可寻址寄存器 (eax、ebx、ecx或edx)

  r 使用任意动态分配的寄存器

  g 使用通用有效的地址即可(eax、ebx、edx、ecx 或者内存变量)

  A 使用eax和edx联合(64bit)

  m 使用内存地址

  o 使用内存地址,并可以加载偏移值

  I 使用常数0-31

  J 使用常数0-63

  K 使用常数0-255

  L 使用常数0-65536

  M 使用常数0-3

  N 使用1字节常数(0-255)

  O 使用常数0-31

  下面的例子不是让自己制定那个变量使用那个寄存器,而是让gcc为你选择

  asm(“leal(%1,%1,4),%0”

  :“r”(y)

  :“0”(x));

  第1句leal(r1,r2,4),r3 语句表示r3=r1+r2&TImes;4。这个例子可以非常快的将x成5.其中“%0”,“%1” 是指gcc自动分配的寄存器。这里%1 代表输入值x要放入的寄存器,”%0“表示输出寄存器。所以如果gcc将r指定为eax的话,那么上面汇编语句的含义为”leal(eax,eax,4),eax“ 注意 如果不希望汇编语句被gcc优化而挪动地方,就需要在asm符号后面添加volaTIle关键字

  asm volaTIle();或者

  __asm__ __volaTIle__();

技术专区

  • 据说嵌入式工程师年薪10万是门槛 达到后你满足了吗?
  • TTR-Driver环视+前方碰撞预警系统
  • 封装/ PCB系统的热分析:挑战和解决方案
  • 华为徐直军:没有任何想法把麒麟芯片对外销售
  • 单片机烧写器是什么 烧写器怎么用
  • 浅谈GNU 嵌入式汇编具体因使用方法已关闭评论
    A+
发布日期:2019年07月14日  所属分类:物联网