1

Armv7 コアを使用してターゲット用にアプリケーションをクロス コンパイルすると、「long long int」を含む変数が正しく出力されません。

typedef long long int vmm_int64;
typedef unsigned long long int vmm_uint64;

int main(int argc, char *argv[])
{
    vmm_int64 a, b, result;

    a = 5;
    b = 24;
    result = 0;

    printf("Initial Values are:\n");
    printf("\t a : %lld \n", a);
    printf("\t b : %lld \n", b);
    printf("\t result : %lld \n", result);

    fflush(stdout);

    result = a + b;

    printf("Final Values are:\n");
    printf("\t a : %lld \n", a);
    printf("\t b : %lld \n", b);
    printf("\t result : %lld \n", result);

    fflush(stdout);

    return 0;
}

出力は次のとおりです。

Initial Values are:
     a : 23639177792
     b : 105243556416
     result : 2164341312
Final Values are:
     a : 23639177792
     b : 105243556416
     result : 126718392896

誰かがここで何が起こっているのか説明してもらえますか? 正しくするにはどうすればよいですか?

もう少し分析した後、私はちょうどそれを観察しました

a = 0x5 (0x00000005 81013a44  which is hex for  23639177792)
b = 0x18 (0x00000018 81013a40 which is hex for 105243556416)

i. result = 0 (0x00000000 81013a40 which is hex for 2164341312)
ii. result = 0x1D (0x0000001D 81013a40 which is hex for 126718392896)

上位 32 ビットには正しい値が含まれています。理由がわかりません

  1. 結果は上位ワードと下位ワードが入れ替わります。
  2. 言葉が入れ替わっていたとしても、なぜ下の言葉にジャンクがあるのか​​。

コンパイラ情報:

arm-none-eabi-gcc -v
Using built-in specs.
COLLECT_GCC=c:\Program Files\CodeSourcery\Sourcery G++ Lite\bin\arm-none-eabi-gcc.exe
COLLECT_LTO_WRAPPER=c:/program files/codesourcery/sourcery g++ lite/bin/../libexec/gcc/arm-none-eabi/4.5.2/lto-wrapper.exe
Target: arm-none-eabi
Configured with: /scratch/janisjo/arm-eabi-lite/src/gcc-4.5-2011.03/configure --build=i686-pc-linux-gnu --host=i686-mingw32 --target=arm-none-eabi --enable-threads --disable-libmudflap --disable-libssp --disable-libstdcxx-pch --enable-extra-sgxxlite-multilibs --with-gnu-as --with-gnu-ld --with-specs='%{save-temps: -fverbose-asm} -D__CS_SOURCERYGXX_MAJ__=2011 -D__CS_SOURCERYGXX_MIN__=3 -D__CS_SOURCERYGXX_REV__=42 %{O2:%{!fno-remove-local-statics: -fremove-local-statics}} %{O*:%{O|O0|O1|O2|Os:;:%{!fno-remove-local-statics: -fremove-local-statics}}}' --enable-languages=c,c++ --disable-shared --enable-lto --with-newlib --with-pkgversion='Sourcery G++ Lite 2011.03-42' --with-bugurl=https://support.codesourcery.com/GNUToolchain/ --disable-nls --prefix=/opt/codesourcery --with-headers=yes --with-sysroot=/opt/codesourcery/arm-none-eabi --with-build-sysroot=/scratch/janisjo/arm-eabi-lite/install/host-i686-mingw32/arm-none-eabi --with-libiconv-prefix=/scratch/janisjo/arm-eabi-lite/obj/host-libs-2011.03-42-arm-none-eabi-i686-mingw32/usr --with-gmp=/scratch/janisjo/arm-eabi-lite/obj/host-libs-2011.03-42-arm-none-eabi-i686-mingw32/usr --with-mpfr=/scratch/janisjo/arm-eabi-lite/obj/host-libs-2011.03-42-arm-none-eabi-i686-mingw32/usr --with-mpc=/scratch/janisjo/arm-eabi-lite/obj/host-libs-2011.03-42-arm-none-eabi-i686-mingw32/usr --with-ppl=/scratch/janisjo/arm-eabi-lite/obj/host-libs-2011.03-42-arm-none-eabi-i686-mingw32/usr --with-host-libstdcxx='-static-libgcc -Wl,-Bstatic,-lstdc++,-Bdynamic -lm' --with-cloog=/scratch/janisjo/arm-eabi-lite/obj/host-libs-2011.03-42-arm-none-eabi-i686-mingw32/usr --with-libelf=/scratch/janisjo/arm-eabi-lite/obj/host-libs-2011.03-42-arm-none-eabi-i686-mingw32/usr --disable-libgomp --enable-poison-system-directories --with-build-time-tools=/scratch/janisjo/arm-eabi-lite/obj/tools-i686-pc-linux-gnu-2011.03-42-arm-none-eabi-i686-mingw32/arm-none-eabi/bin --with-build-time-tools=/scratch/janisjo/arm-eabi-lite/obj/tools-i686-pc-linux-gnu-2011.03-42-arm-none-eabi-i686-mingw32/arm-none-eabi/bin
Thread model: single
gcc version 4.5.2 (Sourcery G++ Lite 2011.03-42) 
4

1 に答える 1

1

ABI を混在させているようです。Android ランタイムが EABI を想定している間に、クロス コンパイラが APCS (旧 ABI) を使用している可能性があります。

この 2 つの重要な違いの 1 つは、64 ビット値がレジスターで渡される方法です。古い ABI は、次に利用可能なレジスタのペアを使用します。

; printf("\t a : %lld \n", a);
load format string into R0
load 'a' into R1 and R2
call printf

一方、EABI は次の偶数アラインされたレジスタ ペアを使用します。

; printf("\t a : %lld \n", a);
load format string into R0
load 'a' into R2 and R3
call printf

a両方の ABI に渡される方法を見てみましょう。

1. 実際: 5 = 0 (high32) および 5 (low32)

OABI: R1 = 0、R2 = 5
EABI: R2 = 0、R3 = 5

  1. 印刷: 23639177792 = 0x581013A40 = 0x5 (high32) および 0x81013A40 (low32)

    OABI: R1 = 5、R2 = 0x81013A40
    EABI: R2 = 5、R3 = 0x81013A40

したがって、コードは 0 を にロードしR1、5 を にロードした可能性が高いですR2が、上位部分は低部分としてprintf解釈R2され、ガベージR3は低部分として解釈されます。生成されたアセンブリを調べることで簡単に確認できます。

修正は簡単です。コンパイラ オプションを使用してEABIコードを生成するか、Android NDK などの Android を特にターゲットとするツールチェーンを使用します。

EDIT : ハイとローのパーツを入れ替えました。正しいバージョンは次のとおりです。

  1. 実際: 5 = 0 (high32) および 5 (low32)

    OABI: R1 = 5、R2 = 0
    EABI: R2 = 5、R3 = 0

  2. 印刷: 23639177792 = 0x581013A40 = 0x5 (high32) および 0x81013A40 (low32)

    OABI: R1 = 0x81013A40、R2 = 5
    EABI: R2 = 0x81013A40、R3 = 5

したがって、証拠は実際には反対のことを示唆しています。あなたのコードはprintfOABI を期待しているのに EABI を使用しています。

于 2013-08-16T12:14:23.990 に答える