首页 | 新闻 | 新品 | 文库 | 方案 | 视频 | 下载 | 商城 | 开发板 | 数据中心 | 座谈新版 | 培训 | 工具 | 博客 | 论坛 | 百科 | GEC | 活动 | 主题月 | 电子展
返回列表 回复 发帖

GNU汇编总结 09

GNU汇编总结 09

如果内联汇编代码中的输入和输出值共享程序中相同的c变量, 则可以指定使用占位符作为
   
    约束值, 如:
   
    __asm__("imull %1, %0"
   
    : "=r"(data2)
   
    : "r"(data1), "0"(data2));
   
    如输入输出值中共享相同的变量data2, 而在输入变量中则可以使用标记0作为输入参数的约束
   
    2, 替换占位符
   
    如果处理很多输入和输出值, 数字型的占位符很快就会变的很混乱, 为了使条理清晰 ,GNU汇编
   
    器(从版本3.1开始)允许声明替换的名称作为占位符。替换的名称在声明输入值和输出值的段中
   
    定义, 格式如下:
   
    %[name]"constraint"(variable)
   
    定义的值name成为内联汇编代码中变量的新的占位符号标识, 如下面的例子:
   
    __asm__("imull %[value1], %[value2]"
   
    : [value2] "=r"(data2)
   
    : [value1] "r"(data1), "0"(data2));
   
    3, 改动寄存器列表
   
    编译器假设输入值和输出值使用的寄存器会被改动, 并且相应的作出处理。程序员不需要在改动的
   
    寄存器列表中包含这些值, 如果这样做了, 就会产生错误消息。 注意改动的寄存器列表中的寄存器
   
    使用完整的寄存器名称, 而不像输入和输出寄存器定义的那样仅仅是单一字母。 在寄存器名称前面
   
    使用百分号符号是可选的。
   
    改动寄存器列表的正确使用方法是, 如果内联汇编代码使用了没有被初始化地声明为输入或者输出
   
    值的其他任何寄存器 , 则要通知编译器。编译器必须知道这些寄存器, 以避免使用他们。如:
   
    int main(void) {
   
    int data1 = 10;
   
    int result = 20;
   
    __asm__("movl %1, %%eax\n\t"
   
    "addl %%eax, %0"
   
    : "=r"(result)
   
    : "r"(data1), "0"(result)
   
    : "%eax");
   
    printf("The result is %d\n", result);
   
    return 0;
   
    }
   
    4, 使用内存位置
   
    虽然在内联汇编代码中使用寄存器比较快, 但是也可以直接使用c变量的内存位置。 约束m用于引用输入值
   
    和输出值中的内存位置。 记住, 对于要求使用寄存器的汇编指令, 仍然必须使用寄存器, 所以不得不定义
   
    保存数据的中间寄存器。如:
   
    int main(void) {
   
    int dividentd = 20;
   
    int divisor = 5;
   
    int result;
   
    __asm__("divb %2\n\t"
   
    "movl %%eax, %0"
   
    : "=m"(result)
   
    : "a"(dividend), "m"(divisor));
   
    printf("The result is %d\n", result);
   
    return 0;
   
    }
   
    5, 处理跳转
   
    内联汇编语言代码也可以包含定义其中位置的标签。 可以实现一般的汇编条件分支和无条件分支, 如:
   
    int main(void) {
   
    int a = 10;
   
    int b = 20;
   
    int result;
   
    __asm__("cmp %1, %2\n\t"
   
    "jge greater\n\t"
   
    "movl %1, %0\n\t"
   
    "jmp end\n"
   
    "greater:\n\t"
   
    "movl %2, %0\n"
   
    "end:"
   
    :"=r"(result)
   
    :"r"(a), "r"(b));
   
    printf("The larger value is %d\n", result);
   
    return 0;
   
    }
   
    在内联汇编代码中使用标签时有两个限制。 第一个限制是只能跳转到相同的asm段内的标签,
   
    不能从-个asm段跳转到另一个asm段中的标签。第二个限制更加复杂一点。 以上程序使用
   
    标签greater和end。 但是, 这样有个潜在的问题, 查看汇编后的代码清单, 可以发现内联
   
    汇编标签也被编码到了最终汇编后的代码中。 这意味着如果在c代码中还有另一个asm段, 就
   
    不能再次使用相同的标签, 否则会因为标签重复使用而导致错误消息。还有如果试图整合使用
   
    c关键字(比如函数名称或者全局变量)的标签也会导致错误
返回列表