c - long long int values are incorrectly printed -


when cross compile application target armv7 core, variables 'long long int' incorrectly printed.

typedef long long int vmm_int64; typedef unsigned long long int vmm_uint64;  int main(int argc, char *argv[]) {     vmm_int64 a, b, result;      = 5;     b = 24;     result = 0;      printf("initial values are:\n");     printf("\t : %lld \n", a);     printf("\t b : %lld \n", b);     printf("\t result : %lld \n", result);      fflush(stdout);      result = + b;      printf("final values are:\n");     printf("\t : %lld \n", a);     printf("\t b : %lld \n", b);     printf("\t result : %lld \n", result);      fflush(stdout);      return 0; } 

the output follows:

initial values are:      : 23639177792      b : 105243556416      result : 2164341312 final values are:      : 23639177792      b : 105243556416      result : 126718392896 

could please explain going on here? should make right?

after more analysis, observed that

a = 0x5 (0x00000005 81013a44  hex  23639177792) b = 0x18 (0x00000018 81013a40 hex 105243556416)  i. result = 0 (0x00000000 81013a40 hex 2164341312) ii. result = 0x1d (0x0000001d 81013a40 hex 126718392896) 

the upper 32 bits contain correct values. don't understand why

  1. the result upper/lower word swapped.
  2. even if words swapped, why there junk in lower word.

compiler info:

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)  

looks you're mixing abis. cross compiler using apcs (aka old abi) while android runtime expects eabi.

one important difference between 2 how 64-bit values passed in registers. old abi uses next available pair of registers, e.g.

; printf("\t : %lld \n", a); load format string r0 load 'a' r1 , r2 call printf 

while eabi uses next even-aligned register pair:

; printf("\t : %lld \n", a); load format string r0 load 'a' r2 , r3 call printf 

let's how a passed both abis:

1. actual: 5 = 0 (high32) , 5 (low32)

oabi: r1 = 0, r2 = 5
eabi: r2 = 0, r3 = 5

  1. printed: 23639177792 = 0x581013a40 = 0x5 (high32) , 0x81013a40 (low32)

    oabi: r1 = 5, r2 = 0x81013a40
    eabi: r2 = 5, r3 = 0x81013a40

so code loaded 0 r1 , 5 r2, printf interpreted r2 high part , garbage r3 low part. can check inspecting generated assembly.

the fix should easy - use compiler option generate eabi code, or use toolchain targets android, e.g. android ndk.

edit: had high , low parts swapped. here's correct version:

  1. actual: 5 = 0 (high32) , 5 (low32)

    oabi: r1 = 5, r2 = 0
    eabi: r2 = 5, r3 = 0

  2. printed: 23639177792 = 0x581013a40 = 0x5 (high32) , 0x81013a40 (low32)

    oabi: r1 = 0x81013a40, r2 = 5
    eabi: r2 = 0x81013a40, r3 = 5

so, evidence suggests opposite: code using eabi while printf expecting oabi.


Comments

Popular posts from this blog

assembly - 8086 TASM: Illegal Indexing Mode -

Java, LWJGL, OpenGL 1.1, decoding BufferedImage to Bytebuffer and binding to OpenGL across classes -

javascript - addthis share facebook and google+ url -