首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >arm和x86体系结构中c/c++语言的区别

arm和x86体系结构中c/c++语言的区别
EN

Stack Overflow用户
提问于 2015-04-13 07:25:49
回答 2查看 11.2K关注 0票数 2

我试图将最初为x86架构编写的代码移植到arm中。

https://github.com/SDLash3D

最初它是为msvc/ was 32开发的,代码中有很多bug,所以可能有UB。

当与gcc一起编译时,代码在x86上工作,但在arm上,它有不同的行为。它似乎失去了一些数据阵列和武器开关不工作。它影响到服务器和客户端库。

应用程序是单线程的,所以它不是同步问题.

默认情况下,Char在arm上没有签名,所以我将-fsigned-char添加到编译器标志中,但它并没有解决问题。arm和x86 c++代码还有什么区别?

我试着用gcc和clang在arm上编译代码,没有什么区别,所以它不是编译器的错误。

P.SI用gcc-4.9 (而不是4.8)编写了x86代码,并得到了相同的行为。之后,我组合了两个编译器,发现这个问题出现在net_encode.c中。

当时,塞巴斯蒂安·切瓦利耶发现

iValue /= pField->multiplier; iValue *= pField->multiplier;

当iValue是整数和pField->乘子==1.0F时,有时会改变整数值。

它可以通过增加检查pField->乘数!= 1.0f在乘前进行修正。

EN

回答 2

Stack Overflow用户

发布于 2015-04-13 07:39:14

如果没有看到您的代码,几乎是不可能说出来的,但是会尝试回答一般的问题。

x86和ARM之间的一个巨大区别是,大多数x86指令都是内部原子的,其中ARM没有这样的东西--您必须明确地说“只执行这组指令”。因此,如果您有由多个线程更新的数据,这可能会影响到您。

个别指令的行为方式也有差异。不知道您的代码是做什么的,这是相当难说它是否影响您的代码,但有一件事情可以击中的是“非对齐访问”,这是完全有效的(虽然不是最优的)在x86,但无效(在大多数模型)的ARM处理器。因此,指针必须与它访问的项的大小对齐。

当然,编译器中的代码生成是不同的,它们可能根据输入代码做出不同的决定,从而最终得到以各种方式不同行为的代码。不止一次打击我的是“参数函数调用的执行顺序”:

代码语言:javascript
运行
复制
func(func1(), func2()); 

请注意,func1()func2()可以先执行。如果您依赖这样的订单,则需要:

代码语言:javascript
运行
复制
t1 = func1();
t2 = func2();
func(t1, t2); 

提示:

如果您还没有启用,请启用尽可能多的警告(至少-Wall)。并修正任何警告

检查#pragma pack或类似的“打包数据结构”,并类似地从char *转换到int *等,因为这些都会导致未对齐的访问问题。

编辑:当然,不同的编译器会有不同的bug,这些bug可能对特定的编译器、处理器和代码组合产生影响,也可能不会产生影响。虽然不太可能出现这种情况,但也存在同样的问题。

票数 10
EN

Stack Overflow用户

发布于 2015-04-13 08:08:03

我并不是真正的专家,但有一些一般性的事情我可以指出。

首先,根据ARM的版本和设置,某些原始类型的大小、签署性和endianness可能与x86 (特别是x86_64)不同。在这方面,写得好的、可移植的代码不应该对这些方面做出任何假设.如果需要特定的大小和签名,可以使用来自<cstdint> / <stdint.h>头的类型。而且你也应该去处理一些事情。

第二,正如Mats提到的,ARM和x86之间最臭名昭著和行为改变的区别之一是内存模型的严格性。简而言之,x86倾向于非常保守(因此,本质上是“安全的”,或者至少是不足为奇的),而ARM则弱得多(因此,可能更快)。这对于并发代码尤其重要。默认情况下,x86上的许多基本操作都是原子的,并且有许多隐式全内存栅栏,它们保证了一般的一致性。这些护卫机制在手臂上没有那么多的默认存在,这会导致很多奇怪的行为。

例如,许多天真的多线程代码会错误地使用volatile变量在线程之间共享信息或信号。在许多情况下,由于其保守的内存模型,这在x86上可以正常工作。但是在ARM架构上,这个代码很可能被破坏了。

最后,一般来说,不同的体系结构在某些操作上的行为会略有不同。所有这些差异通常属于标准的“未定义行为”或“实现定义”类别。这些是最难找到的but,因为未定义的行为通常意味着在一个体系结构(和编译器)上会发生一件事情,这可能是可以的,但是在另一个体系结构上,会发生一些事情,可能是而不是

有一些工具可以帮助您解决所有这些问题。主要的工具是所谓的“消毒液”。这些工具测试您的运行时代码将大量检查与所有这些相关的各种问题(例如,您可以使用工作的x86代码运行它们,并指出在ARM或其他地方可能有不同行为的“危险”事件)。您可以尝试UBSan (用于UB操作的未定义行为清除器)、TSan (用于数据争用和危险的跨线程内存访问)和ASan (地址清除器,用于一般的内存调试),这些都可以在Clang和GCC下面使用。我不知道这些工具是否有什么特别的东西可以帮助ARM,或者它们甚至是针对ARM,但至少,解决它们在x86上指向的任何问题在移植到ARM时都会有很大的帮助。

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

https://stackoverflow.com/questions/29599919

复制
相关文章

相似问题

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