首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >"+&r“和"+r”有什么区别?

"+&r“和"+r”有什么区别?
EN

Stack Overflow用户
提问于 2017-08-26 12:50:51
回答 1查看 579关注 0票数 5

GCC的内联汇编程序识别声明器=r=&r。这对我来说很有意义:=r允许汇编程序重用一个输入寄存器进行输出。

然而,GCC的内联汇编程序也能识别声明器+r+&r。这些对我来说没什么意义。毕竟,+r+&r之间的区别不是没有区别的吗?单靠+r不足以让编译器为单独使用一个变量保留一个寄存器吗?

例如,下面的GCC代码有什么问题?

代码语言:javascript
运行
复制
#include <stdio.h>
int main()
{
    int a = 0;
    printf("Initially, a == %d.\n", a);
    /* The architecture is amd64/x86-64. */
    asm(
        "inc %[a]\n"
        : [a] "+r" (a)
        : : "cc"
    );
    printf("However, after incrementation, a == %d.\n", a);
    return 0;
}

顺便注意一下,我的内联程序集缺少一个输入声明,因为在我(可能是错误的)头脑中,+r涵盖了输入、失败、输出等所有内容。请问我误解了什么?

背景

我在汇编中编写了8位和16位微控制器,但很少或根本没有在托管环境中编写汇编的经验。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2017-08-26 14:51:56

默认情况下,GCC假设内联程序集语句由一个简单的程序集指令组成,该程序集指令在写入任何输出操作数之前消耗其所有输入操作数。当编写使用多个程序集指令的内联程序集语句时,这个假设经常被打破,因此需要使用早期的clobber约束修饰符&来指示在使用所有输入操作数之前将输出操作数写入哪个输出操作数。这对于使用=修饰符的输出操作数和使用+的读/写输出操作数都是必要的。例如,考虑以下两个功能:

代码语言:javascript
运行
复制
int
foo() {
    int a = 1;
    asm("add %1, %0" : "+r" (a) : "r" (1));
    return a;
}

int
bar() {
    int a = 1;
    asm("add %1, %0\n\t"
        "add %1, %0"
        : "+r" (a) : "r" (1));
    return a;
}

两条内联程序集语句都使用相同的操作数和相同的约束,但是foo中唯一的内联程序集语句是正确的,bar中的内联程序集语句是坏的。启用优化后,GCC为这两个函数生成以下代码:

代码语言:javascript
运行
复制
_foo:
    movl    $1, %eax
/APP
    add %eax, %eax
/NO_APP
    ret

_bar:
    movl    $1, %eax
/APP
    add %eax, %eax
    add %eax, %eax
/NO_APP
    ret

GCC认为没有理由不对两个内联程序集语句中的两个操作数使用相同的寄存器EAX。虽然这在foo中不是问题,但它会导致bar计算错误的结果为4,而不是预期的3。

正确的bar版本将使用早期的clobber修饰符:

代码语言:javascript
运行
复制
int
baz() {
    int a = 1;
    asm("add %1, %0\n\t"
        "add %1, %0"
        : "+&r" (a) : "r" (1));
    return a;
}
代码语言:javascript
运行
复制
_baz:
    movl    $1, %eax
    movl    %eax, %edx
/APP
    add %edx, %eax
    add %edx, %eax
/NO_APP
    ret

在编译baz时,GCC知道对两个操作数使用不同的寄存器,因此在第二次读取输入操作数之前修改读/写输出操作数并不重要。

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

https://stackoverflow.com/questions/45895564

复制
相关文章

相似问题

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