首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >使用程序集代码从内存复制到c++中注册

使用程序集代码从内存复制到c++中注册
EN

Stack Overflow用户
提问于 2013-08-10 01:54:45
回答 2查看 1.1K关注 0票数 0

在将c++程序转换为程序集时,我遇到了一个问题,我不得不这样做

这是我的c++代码

代码语言:javascript
复制
for(int i=0;i<rows-4;i++,a+=4,b+=4,c+=4,d+=4,e+=4,f+=4,x+=4,o+=4){
  for(int j=0;j<cols-4;j++,a++,b++,c++,d++,e++,f++,x++,o++){
    *o=*a>*x;
    *o=*b>*x|(*o<<1);
    *o=*c>*x|(*o<<1);
    *o=*d>*x|(*o<<1);
    *o=*e>*x|(*o<<1);
    *o=*f>*x|(*o<<1);
    }
}

O是输出数据的指针,而a、b、c、d、e、f和x是输入数据的指针。我想要的只是将输入数据中的比较保存到一个变量中,但是当要处理的数据很大时,上面的代码就没有效率了。与在寄存器中保存临时数据相比,该程序需要更多的时间将数据保存到内存中。

所以我想做的就是让这个过程在寄存器中完成。我尝试的是将x引用的数据存储在EBX中,将EBX与包含a(和b,c,d,e,f)引用值的ECX进行比较,将比较结果保存到EAX,并将EAX寄存器左移,以便将所有比较存储在一个变量中。在所有6个比较都已处理完之后,ECX的值将被复制到内存中。

这就是我所做的,我的程序运行速度可以快两倍,但是我得到的所有值都是零。也许我做错了?

代码语言:javascript
复制
      __asm__(
"xorl %%eax,%%eax;"
"xorl %%ebx,%%ebx;"
"xorl %%ecx,%%ecx;"

"movl %1, %%ebx;"

//start here
"movl %2,%%ecx;"
"cmp %%ebx,%%ecx;"
"jnz .one;"
"orl $0x1,%%eax;"

".one:;"
"shll $1,%%eax;"
"movl %3,%%ecx;"
"cmp %%ebx,%%ecx;"
"jnz .two;"
"orl $0x1,%%eax;"

".two:;"
"shll $1,%%eax;"
"movl %4,%%ecx;"
"cmp %%ebx,%%ecx;"
"jnz .three;"
"orl $0x1,%%eax;"

".three:;"
"shll $1,%%eax;"
"movl %5,%%ecx;"
"cmp %%ebx,%%ecx;"
"jnz .four;"
"orl $0x1,%%eax;"

".four:"
"shll $1,%%eax;"
"movl %6,%%ecx;"
"cmp %%ebx,%%ecx;"
"jnz .five;"
"orl $0x1,%%eax;"

".five:"
"shll $1,%%eax;"
"movl %7,%%ecx;"
"cmp %%ebx,%%ecx;"
"jnz .six;"
"orl $0x1,%%eax;"

".six:"
//output
"movl %%eax,%0;"

:"=r"(sett)
:"r"((int)*x),"r"((int)*a) ,"r"((int)*b) ,"r"((int)*c) ,"r"((int)*d),"r"((int)*e),"r"((int)*f) /* input */
  );
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2013-08-10 04:37:57

有几种选择:

1)丢弃手工编写的程序集代码。你说C代码很慢,告诉我们有多少。我看不出如何以任何有意义的方式来衡量这种差异,因为asm版本甚至没有产生正确的结果。换句话说,尝试asm("nop;");,这是生成不正确结果的一种更快的方法。

2)重写C代码,只读取一次*x;将结果保存在一个临时变量中,最后只写入*o

3)如果适合您的语义(并得到编译器的支持),则使用restrict/__restrict/__restrict__ (来自C99,通常作为扩展在C++中可用)来修饰指针,这样编译器就不会知道在写入*o时输入变量的变化。

4)编译器具有较好的自动展开循环能力。它可能需要命令行选项、#pragma指令或扩展/属性的组合。

编辑

这就是我的意思,把它改写成使用临时的:

代码语言:javascript
复制
for(int i=0;i<rows-4;i++,a+=4,b+=4,c+=4,d+=4,e+=4,f+=4,x+=4,o+=4){
    for(int j=0;j<cols-4;j++,a++,b++,c++,d++,e++,f++,x++,o++){
        uint32_t tmp_x = *x;
        *o = (*a > tmp_x ? 0x20 : 0)
          |  (*b > tmp_x ? 0x10 : 0)
          |  (*c > tmp_x ? 0x08 : 0)
          |  (*d > tmp_x ? 0x04 : 0)
          |  (*e > tmp_x ? 0x02 : 0)
          |  (*f > tmp_x ? 0x01 : 0);
    }
}

这有什么区别?在最初的版本中,x是从每一个作业中读取的。编译器不知道ox指向不同的位置;在最坏的情况下,编译器每一次都必须从x读取,因为通过向o写入,x中的值可能会发生变化。

当然,这段代码有不同的语义:如果您真的让o别名使用其他指针之一,那么它将执行与原始指针不同的操作。

票数 1
EN

Stack Overflow用户

发布于 2013-08-12 15:49:21

我假设你使用的是最近的英特尔芯片。...and我认为您真正想要使用的是(如果使用它来表示Cray:-)向量功能(相当有限的话),这些被称为AVX。还有一些库可以在C/ C ++下实现这一点,首先从googling和C开始。

尽管如此,您还可以告诉编译器使用“Register keyword in C++”关键字在寄存器中存储一些变量,请参阅此

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

https://stackoverflow.com/questions/18157952

复制
相关文章

相似问题

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