首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >用汇编语言编写C程序函数

用汇编语言编写C程序函数
EN

Stack Overflow用户
提问于 2015-09-05 19:52:05
回答 2查看 657关注 0票数 0

我必须实现set_bit函数,它应该是一个原子操作。我在linux源代码中找到了这方面的汇编代码。(我正在使用sparc),并希望将其更改为可以在C程序中使用的函数。

代码语言:javascript
复制
    static void set_bit(unsigned int nr, unsigned int *addr)
    {
    //  *vec |= 1<<bit;  <== original non-atomic C code
    //set_bit:      /* %o0=nr, %o1=addr */   <== nr is in %o0, addr in %o1 by sparc rule
__asm__ __volatile__ (
    "srlx   %o0, 6, %g1"
    "mov    1, %o2"
    "sllx   %g1, 3, %g3"
    "and    %o0, 63, %g2"
    "sllx   %o2, %g2, %o2"
    "add    %o1, %g3, %o1"
"1: ldx [%o1], %g7"
    "or %g7, %o2, %g1"
    "casx   [%o1], %g7, %g1"
    "cmp    %g7, %g1"
    "bne,pn %xcc, 2f"
     "nop"
    "retl"
    "nop"
    : "=m"(addr) // output
    : "m"(nr) // input
    : );

这是正确的吗?我是否在最后一行列出了所有的clobberd寄存器?

我看到下面的错误消息..

代码语言:javascript
复制
../../../../../rtems-4.10.99-src/c/src/libchip/sdmmc/ald-sd-card.c:135:1: error: invalid 'asm': invalid operand output code
 __asm__ __volatile__ (
 ^
../../../../../rtems-4.10.99-src/c/src/libchip/sdmmc/ald-sd-card.c:135:1: error: invalid 'asm': invalid operand output code
../../../../../rtems-4.10.99-src/c/src/libchip/sdmmc/ald-sd-card.c:135:1: error: invalid 'asm': operand number out of range

      ^
EN

回答 2

Stack Overflow用户

发布于 2015-09-05 22:14:55

我认为您应该在字符串中的每一行只编写一条指令(在每条指令的末尾添加\n\t )。

代码语言:javascript
复制
    static void set_bit(unsigned int nr, unsigned int *addr)
    {
    //  *vec |= 1<<bit;  <== original non-atomic C code
    //set_bit:      /* %o0=nr, %o1=addr */   <== nr is in %o0, addr in %o1 by sparc rule
__asm__ __volatile__ (
    "srlx   %o0, 6, %g1\n\t"
    "mov    1, %o2\n\t"
    "sllx   %g1, 3, %g3\n\t"
    "and    %o0, 63, %g2\n\t"
    "sllx   %o2, %g2, %o2\n\t"
    "add    %o1, %g3, %o1\n\t"
"1: ldx [%o1], %g7\n\t"
    "or %g7, %o2, %g1\n\t"
    "casx   [%o1], %g7, %g1\n\t"
    "cmp    %g7, %g1\n\t"
    "bne,pn %xcc, 2f\n\t"
     "nop\n\t"
    "retl\n\t"
    "nop\n\t"
    : "=m"(addr) // output
    : "m"(nr) // input
    : );
    }
票数 0
EN

Stack Overflow用户

发布于 2015-09-06 18:33:40

看起来你用的是GCC。

正如@MikeCAT所说,指令需要在单独的行上。

您需要将寄存器名称中的所有%加倍。%%将成为输出程序集中的%

根据

规则,地址nr位于%o0,地址位于%o1

没有这样的规则,你可能会想到函数调用ABI,它不适用于内联汇编。如您所问,GCC期望将addr写入内存位置%0,而nr位于内存位置%1

:“=m”(地址) //输出:"m"(nr) //输入

但是addr不是输出。*addr是一个输入/输出,或者addr是一个输入,并且"memory"必须在clobber列表中。对于nr来说,寄存器将是更好的位置

:"+m"(*addr) //输入输出:"r"(nr) //输入

你不应该把retl放在那里,因为它跳到了一个未定义的位置,控制流应该到达终点。

您必须列出所有更改的寄存器,要么作为输出,要么作为缓冲器。

如果这被认为是一个内存屏障,那么"memory"必须出现在拦截器列表中。

我建议您参考GCC Manual

编辑:错过了一个指针引用。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/32412746

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档