您好我正在开发一个程序,我需要处理一个包含一系列可能未对齐(有时也是)的浮点数的数据blob。 我正在使用gcc 4.6.2编译ARM cortex-a8。 我对生成的汇编代码有疑问:
作为示例,我写了一个最小的例子:对于以下测试代码
float aligned[2];
float *unaligned = (float*)(((char*)aligned)+2);
int main(int argc, char **argv)
{
float f = unaligned[0];
return (int)f;
}
编译器(gcc 4.6.2 - with optimization -O3)生成
00008634 <main>:
8634: e30038ec movw r3, #2284 ; 0x8ec
8638: e3403001 movt r3, #1
863c: e5933000 ldr r3, [r3]
8640: edd37a00 vldr s15, [r3]
8644: eefd7ae7 vcvt.s32.f32 s15, s15
8648: ee170a90 vmov r0, s15
864c: e12fff1e bx lr
此处的编译器无法知道数据是否已对齐,但从不会使用需要对齐数据的VLDR,否则程序将因总线错误而崩溃。
现在这是我的实际问题:编译器是否正确,我需要在C ++代码中处理对齐,或者这是编译器中的错误?
我还可以添加我当前的解决方法,它可以在访问该值之前使用gcc进行复制。诀窍是定义一个只包含带有gcc packed属性的float的结构,并通过struct指针访问数据。代码段:
struct FloatWrapper { float f; } __attribute__((packed));
const FloatWrapper *x = reinterpret_cast<const FloatWrapper *>(rawX.data());
const FloatWrapper *y = reinterpret_cast<const FloatWrapper *>(rawY.data());
for (size_t i = 0; i < vertexCount; ++i) {
vertices[i].x = x[i].f;
vertices[i].y = y[i].f;
}
答案 0 :(得分:3)
由于您指出了ARM ARM A3.2.1
个州,无论SCTLR.A
值如何,VLDR
都会生成Alignment fault
。
我在Cortex-A9上测试了你的例子,我得到了
# float_align
[1] + Stopped (signal) float_align
但是,我对ARM Cortex-A8 TRM 4.2.1感到困惑,它说明了
如果未指定对齐限定符且A = 1,则在未与元素大小对齐时采用对齐错误。
如果未指定对齐限定符且A = 0,则将其视为未对齐访问。
这可能是一个半假的解释,因为ARM ARM
提供了更详细的说明信息表。
所以我认为答案是,你需要自己处理对齐,因为编译器无法找出你在所有情况下加载的地址,比如链接后地址可能等等。