1
    以下代码在 linux-x86、darwin-x86 上运行良好,但不适用于 ios-armv7。

    正确的输出应该是:
        m[0]:0.500000,v:0.500000
        m[1]:0.500000,v:0.500000
        m[2]:0.500000,v:0.500000
        m[3]:0.500000,v:0.500000
        m[4]:0.500000,v:0.500000

    但我发现错误的输出:
        m[0]:0.500000,v:0.500000
        m[1]:0.500000,v:0.000000
        m[2]:0.500000,v:0.000000
        m[3]:0.500000,v:0.000000
        m[4]:0.500000,v:0.000000

    当它为 ios-armv7 构建时,我也发现了它的缺点:

    [a] 删除函数'func',将函数体移动到'main'函数,它工作正常
    [b] 将数组 'm[5]' 声明为 'double m[5]',它工作正常
    [c] 将变量 'v' 设置为 'v = 0.5 或 v = sqrt(2.0f/8)',它工作正常
    [d] 如果 gcc 优化选项是 '-O0',它可以正常工作,但是当它是 '-O1 或 -O2' 时,会出现错误输出


    我的 iPad1 被破解了,所以我可以在我的 MacBook Air 上交叉编译一个可执行文件,然后将可执行文件“scp”到 iPad1 并运行它。以下是详细信息:

    1. 在 Mac 上交叉编译一个可执行文件:
    /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/usr/bin/llvm-gcc -O1 -Wall -arch armv7 -mcpu=cortex-a8 -isysroot /Applications/Xcode.app/Contents/ Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS6.1.sdk -I/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS6.1.sdk/usr/include - D__IPHONE_OS__ -miphoneos-version-min=4.0 foo.c

    2. 'scp' 可执行文件到 iPad
    scp a.out mobile@192.168.1.106:~

    3. 'ssh' 到 iPad
    ssh mobile@192.168.1.106 #默认密码是'alpine'

    4. 在 iPad 上运行 a.out
    ./a.out
#include <stdio.h>
#include <math.h>

int
func(int n) /* [a] */
{
    int i;
    float m[5]; /* [b] */
    double v;

    v = sqrt(2.0f/n); /* [c] */

    for(i=0;i<5;++i) {
        m[i]=v;
        printf("m[%d]: %f, v: %f\n", i, m[i], v);
    }

    return 0;
}


int
main(int argc, char **argv)
{
    return func(8);
}

您还可以在https://gist.github.com/ashun/5992120上找到整个代码

以下是组装。你可以在命令'vim -d'的帮助下找到不同之处

  1. 前面代码的汇编,将数组'm[5]'声明为'double m[5]'
        .section __TEXT,__text,regular,pure_instructions
        .section __TEXT,__textcoal_nt,coalesced,pure_instructions
        .section __TEXT,__const_coal,coalesced
        .section __TEXT,__picsymbolstub4,symbol_stubs,none,16
        .section __TEXT,__StaticInit,regular,pure_instructions
        .syntax 统一
        .section __TEXT,__text,regular,pure_instructions
        .globl _func
        .对齐 2
        .code 16
        .thumb_func _func
    _func:
        推 {r4, r5, r6, r7, lr}
        添加 r7, sp, #12
        str r8,[sp,#-4]!
        潜艇,#8
        vmov.f32 s0, #2.000000e+00
        movw r8, :lower16:(L_.str-(LPC0_0+4))
        vmov s2, r0
        movt r8, :upper16:(L_.str-(LPC0_0+4))
        vcvt.f32.s32 d1, d1
    LPC0_0:
        添加 r8, 电脑
        移动 r4, #0
        vdiv.f32 s0, s0, s2
        vsqrt.f32 s0, s0
        vcvt.f64.f32 d16, s0
        vmov r5, r6, d16
    LBB0_1:
        移动 r1, r4
        移动 r0, r8
        移动 r2, r5
        移动 r3, r6
        vstr.64 d16,[sp]
        添加 r4, #1
        blx _printf
        cmp r4, #5
        bne LBB0_1
        移动 r0, #0
        添加 sp,#8
        ldr r8, [sp], #4
        弹出 {r4, r5, r6, r7, 电脑}

        .globl _main
        .对齐 2
        .code 16
        .thumb_func _main
    _主要的:
        推 {r7, lr}
        mov r7, sp
        移动 r0, #8
        bl _func
        移动 r0, #0
        弹出 {r7, 电脑}

        .section __TEXT,__cstring,cstring_literals
    L_.str:
        .asciz "m[%d]: %f, v: %f\n"


    .subsections_via_symbols
  1. 前面代码的汇编,将数组'm[5]'声明为'double m[5]'
        .section __TEXT,__text,regular,pure_instructions
        .section __TEXT,__textcoal_nt,coalesced,pure_instructions
        .section __TEXT,__const_coal,coalesced
        .section __TEXT,__picsymbolstub4,symbol_stubs,none,16
        .section __TEXT,__StaticInit,regular,pure_instructions
        .syntax 统一
        .section __TEXT,__text,regular,pure_instructions
        .globl _func
        .对齐 2
        .code 16
        .thumb_func _func
    _func:
        推 {r4, r5, r6, r7, lr}
        添加 r7, sp, #12
        str r8,[sp,#-4]!
        **vpush {d8}**
        潜艇,#8
        vmov.f32 s0, #2.000000e+00
        movw r8, :lower16:(L_.str-(LPC0_0+4))
        vmov s2, r0
        movt r8, :upper16:(L_.str-(LPC0_0+4))
        vcvt.f32.s32 d1, d1
    LPC0_0:
        添加 r8, 电脑
        移动 r4, #0
        vdiv.f32 s0, s0, s2
        vcvt.f64.f32 d16, s0
        vsqrt.f64 d8, d16
        vmov r5, r6, d8
    LBB0_1:
        移动 r1, r4
        移动 r0, r8
        移动 r2, r5
        移动 r3, r6
        vstr.64 d8, [sp]
        添加 r4, #1
        blx _printf
        cmp r4, #5
        bne LBB0_1
        移动 r0, #0
        添加 sp,#8
        流行音乐 {d8}
        ldr r8, [sp], #4
        弹出 {r4, r5, r6, r7, 电脑}

        .globl _main
        .对齐 2
        .code 16
        .thumb_func _main
    _主要的:
        推 {r7, lr}
        mov r7, sp
        移动 r0, #8
        bl _func
        移动 r0, #0
        弹出 {r7, 电脑}

        .section __TEXT,__cstring,cstring_literals
    L_.str:
        .asciz "m[%d]: %f, v: %f\n"


    .subsections_via_symbols
4

1 回答 1

1

目前尚不清楚哪个程序集出错,因为两者都标记为“将数组声明m[5]double m[5]”,不幸的是我没有硬件也没有交叉编译器来重现您的问题。

值得注意的是,两个汇编代码中的循环非常相似。唯一的区别v是位于d16第一个和d8第二个中。v传递给 的位于printf两个循环中,并在调用之前(r5,r6)正确复制到。对于可变参数函数,与非可变参数函数相反,不应使用浮点寄存器来传递参数。因此,两个循环看起来都是正确的。(r2,r3)printf

我能想到的唯一解释是用于编译代码的 ABI 与包含printf. 特别是考虑到编译的代码来自交叉编译器,我假设它printf来自系统上的动态库。由于printf被称为符合 ARM 的 EABI,我认为该错误在printf库中。

如果您的交叉编译器允许静态链接,您可以尝试这样做,因为您将使用与编译器对应的库。当然应用程序变得更大,但它至少可以证实对printf. 您可能需要检查该库是否使用符合 EABI 的编译器进行编译。如果您可以printf在 iPad 上的调试器上单步执行,那么您应该能够确定从哪里printf获取浮点参数。它应该从(r2,r3).

不幸的是,我不能给出一个结论性的答案,但我希望我对进一步调查的建议是有帮助的。

于 2013-07-15T10:20:45.877 回答