Невозможно записать в регистр ARM R4: функция или ошибка?

Недавно я столкнулся со странным поведением ARM Cortex-A8 при его программировании. в ассемблере. Всякий раз, когда я MOV что-либо в R4, моя программа вылетает (дамп стека ниже)

10-14 09:48:43.117: INFO/DEBUG(3048): Build fingerprint: 'google/soju/crespo:2.3.6/GRK39F/189904:user/release-keys'
10-14 09:48:43.121: INFO/DEBUG(3048): pid: 7082, tid: 7082  >>> neontests <<<
10-14 09:48:43.121: INFO/DEBUG(3048): signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 00000001
10-14 09:48:43.125: INFO/DEBUG(3048):  r0 00000001  r1 afa025b6  r2 00000000  r3 bec77051
10-14 09:48:43.128: INFO/DEBUG(3048):  r4 00000001  r5 bec7704c  r6 00000001  r7 00000004
10-14 09:48:43.128: INFO/DEBUG(3048):  r8 00000005  r9 00000000  10 4214cca4  fp 800a5368
10-14 09:48:43.128: INFO/DEBUG(3048):  ip afa03110  sp bec77010  lr afa0133b  pc afd37b42  cpsr 60000030
10-14 09:48:43.132: INFO/DEBUG(3048):  d0  0000000200000053  d1  0000000400000074
10-14 09:48:43.132: INFO/DEBUG(3048):  d2  000000060000006f  d3  0000000800000070
10-14 09:48:43.132: INFO/DEBUG(3048):  d4  006f0065006e002e  d5  007300650074006e
10-14 09:48:43.136: INFO/DEBUG(3048):  d6  0000000c00000005  d7  0000002000000015
10-14 09:48:43.136: INFO/DEBUG(3048):  d8  0000000c00000005  d9  0000002000000015
10-14 09:48:43.140: INFO/DEBUG(3048):  d10 0000000000000000  d11 0000000000000000
10-14 09:48:43.140: INFO/DEBUG(3048):  d12 0000000000000000  d13 0000000000000000
10-14 09:48:43.140: INFO/DEBUG(3048):  d14 0000000000000000  d15 0000000000000000
10-14 09:48:43.144: INFO/DEBUG(3048):  d16 800220e8401644a8  d17 bff0000000000000
10-14 09:48:43.144: INFO/DEBUG(3048):  d18 3ff0000000000000  d19 0000000000000000
10-14 09:48:43.148: INFO/DEBUG(3048):  d20 0000000000000000  d21 0000000000000000
10-14 09:48:43.148: INFO/DEBUG(3048):  d22 3ff0000000000000  d23 0000000000000000
10-14 09:48:43.148: INFO/DEBUG(3048):  d24 3ff0000000000000  d25 0000000000000000
10-14 09:48:43.148: INFO/DEBUG(3048):  d26 0000000000000000  d27 0000000000000000
10-14 09:48:43.148: INFO/DEBUG(3048):  d28 0000000000000000  d29 0000000000000000
10-14 09:48:43.148: INFO/DEBUG(3048):  d30 0000000000000000  d31 0000000000000000
10-14 09:48:43.148: INFO/DEBUG(3048):  scr 20000012
10-14 09:48:43.195: INFO/DEBUG(3048):          #00  pc 00037b42  /system/lib/libc.so
10-14 09:48:43.195: INFO/DEBUG(3048):          #01  pc 00001338  /system/lib/liblog.so
10-14 09:48:43.199: INFO/DEBUG(3048):          #02  pc 00001482  /system/lib/liblog.so
10-14 09:48:43.199: INFO/DEBUG(3048):          #03  pc 00000c54  /data/data/neontests/lib/libneon_tests.so
10-14 09:48:43.199: INFO/DEBUG(3048):          #04  pc 00017e34  /system/lib/libdvm.so
10-14 09:48:43.199: INFO/DEBUG(3048):          #05  pc 0004968c  /system/lib/libdvm.so
10-14 09:48:43.199: INFO/DEBUG(3048):          #06  pc 0004ee62  /system/lib/libdvm.so
10-14 09:48:43.199: INFO/DEBUG(3048):          #07  pc 0001d034  /system/lib/libdvm.so
10-14 09:48:43.199: INFO/DEBUG(3048):          #08  pc 000220e4  /system/lib/libdvm.so
10-14 09:48:43.199: INFO/DEBUG(3048):          #09  pc 00020fdc  /system/lib/libdvm.so
10-14 09:48:43.199: INFO/DEBUG(3048):          #10  pc 0005fdde  /system/lib/libdvm.so
10-14 09:48:43.203: INFO/DEBUG(3048):          #11  pc 00067b52  /system/lib/libdvm.so
10-14 09:48:43.203: INFO/DEBUG(3048):          #12  pc 0001d034  /system/lib/libdvm.so
10-14 09:48:43.203: INFO/DEBUG(3048):          #13  pc 000220e4  /system/lib/libdvm.so
10-14 09:48:43.203: INFO/DEBUG(3048):          #14  pc 00020fdc  /system/lib/libdvm.so
10-14 09:48:43.203: INFO/DEBUG(3048):          #15  pc 0005fc40  /system/lib/libdvm.so
10-14 09:48:43.203: INFO/DEBUG(3048):          #16  pc 0004c126  /system/lib/libdvm.so
10-14 09:48:43.203: INFO/DEBUG(3048):          #17  pc 00032572  /system/lib/libandroid_runtime.so
10-14 09:48:43.203: INFO/DEBUG(3048):          #18  pc 0003341e  /system/lib/libandroid_runtime.so
10-14 09:48:43.203: INFO/DEBUG(3048):          #19  pc 00008cca  /system/bin/app_process
10-14 09:48:43.207: INFO/DEBUG(3048):          #20  pc 00014b52  /system/lib/libc.so
10-14 09:48:43.207: INFO/DEBUG(3048): code around pc:
10-14 09:48:43.207: INFO/DEBUG(3048): afd37b20 18801889 c003f810 c003f801 d2f93b01 
10-14 09:48:43.207: INFO/DEBUG(3048): afd37b30 bf00bdf0 2200b510 3201e003 4618b90b 
10-14 09:48:43.207: INFO/DEBUG(3048): afd37b40 5c83e004 42a35c8c 1b18d0f7 bf00bd10 
10-14 09:48:43.207: INFO/DEBUG(3048): afd37b50 b152b530 5cc42300 42ac5ccd 1b60d001 
10-14 09:48:43.207: INFO/DEBUG(3048): afd37b60 b114e004 429a3301 2000d1f5 bf00bd30 
10-14 09:48:43.207: INFO/DEBUG(3048): code around lr:
10-14 09:48:43.207: INFO/DEBUG(3048): afa01318 fffffff4 00001e20 b088b570 4615460c 
10-14 09:48:43.207: INFO/DEBUG(3048): afa01328 b9099001 447c4c28 46204928 f7ff4479 
10-14 09:48:43.207: INFO/DEBUG(3048): afa01338 2800edc4 4926d02e 22034620 f7ff4479 
10-14 09:48:43.207: INFO/DEBUG(3048): afa01348 b338edc2 46204923 f7ff4479 b308edb6 
10-14 09:48:43.207: INFO/DEBUG(3048): afa01358 46204921 f7ff4479 b1d8edb0 4620491f 
10-14 09:48:43.207: INFO/DEBUG(3048): stack:
10-14 09:48:43.207: INFO/DEBUG(3048):     bec76fd0  800a5368  
10-14 09:48:43.207: INFO/DEBUG(3048):     bec76fd4  afd1c701  /system/lib/libc.so
10-14 09:48:43.207: INFO/DEBUG(3048):     bec76fd8  bec771f0  
10-14 09:48:43.207: INFO/DEBUG(3048):     bec76fdc  bec77051  
10-14 09:48:43.207: INFO/DEBUG(3048):     bec76fe0  0000ce60  
10-14 09:48:43.207: INFO/DEBUG(3048):     bec76fe4  000003fa  
10-14 09:48:43.207: INFO/DEBUG(3048):     bec76fe8  ffff0208  
10-14 09:48:43.207: INFO/DEBUG(3048):     bec76fec  bec7704c  
10-14 09:48:43.207: INFO/DEBUG(3048):     bec76ff0  000003ff  
10-14 09:48:43.207: INFO/DEBUG(3048):     bec76ff4  00000000  
10-14 09:48:43.210: INFO/DEBUG(3048):     bec76ff8  00000003  
10-14 09:48:43.210: INFO/DEBUG(3048):     bec76ffc  00000004  
10-14 09:48:43.210: INFO/DEBUG(3048):     bec77000  80400d90  /data/data/neontests/lib/libneon_tests.so
10-14 09:48:43.210: INFO/DEBUG(3048):     bec77004  bec7704c  
10-14 09:48:43.210: INFO/DEBUG(3048):     bec77008  df002777  
10-14 09:48:43.210: INFO/DEBUG(3048):     bec7700c  e3a070ad  
10-14 09:48:43.210: INFO/DEBUG(3048): #00 bec77010  00000001  
10-14 09:48:43.210: INFO/DEBUG(3048):     bec77014  afa0133b  /system/lib/liblog.so
10-14 09:48:43.210: INFO/DEBUG(3048): #01 bec77018  80400420  /data/data/neontests/lib/libneon_tests.so
10-14 09:48:43.210: INFO/DEBUG(3048):     bec7701c  00000004  
10-14 09:48:43.210: INFO/DEBUG(3048):     bec77020  bec7701c  
10-14 09:48:43.210: INFO/DEBUG(3048):     bec77024  00000001  
10-14 09:48:43.210: INFO/DEBUG(3048):     bec77028  80400d90  /data/data/neontests/lib/libneon_tests.so
10-14 09:48:43.210: INFO/DEBUG(3048):     bec7702c  00000014  
10-14 09:48:43.210: INFO/DEBUG(3048):     bec77030  00000000  
10-14 09:48:43.210: INFO/DEBUG(3048):     bec77034  00000000  
10-14 09:48:43.210: INFO/DEBUG(3048):     bec77038  bec7704c  
10-14 09:48:43.210: INFO/DEBUG(3048):     bec7703c  afd4d5c8  
10-14 09:48:43.210: INFO/DEBUG(3048):     bec77040  00000001  
10-14 09:48:43.210: INFO/DEBUG(3048):     bec77044  afa01487  /system/lib/liblog.so

Редактировать : Дамп стека выше является результатом следующего кода (извинения, выделение сборки GNU, кажется, будет немного странно):

.arm
.global asm_test

asm_test:

    mov r0, #4 @make sure r0 is not the same as r4   
    mov r4, #1 @move to r4 something different from r0

    mov pc, lr @return from function

Я вызываю это из (родного) C следующим образом:

#include 
#include 
#include 
#include 
#include 
#include 
#include "com_something_neontests_NativeLib.h"

extern volatile int asm_test(void);

JNIEXPORT jint JNICALL Java_com_something_neontests_NativeLib_asmTry
  (JNIEnv * env, jobject obj)
{

    __android_log_print(ANDROID_LOG_INFO, "com.something.neontests", "Start!");

    asm_test();

    __android_log_print(ANDROID_LOG_INFO, "com.something.neontests", "Done!");


    return 0;
}

Вот несколько вещей, которые я заметил. Во-первых, всякий раз, когда я назначаю что-либо для R4, будь то MOV R4 , # 2 или ADD R4, R0, R1 , результат действительно попадает в R4 до сбоя программы, но тот же результат всегда заканчивается в R0.Я также обнаружил, что могу POP ​​ вещи из стека в R4. Никакие другие регистры не демонстрируют такого поведения. Код сборки компилируется с использованием Android NDK, который, как мне кажется, использует GCC 4.4.3. Я тестировал его на нескольких телефонах Android, и все, кажется, согласовано.

Я знаю, что все регистры разделены так, что R0-R3 принимает аргументы, R4-R12 - регистры переменных, затем есть специальные регистры и так далее. Возможно, такое поведение вызвано каким-то соглашением о вызовах C, о котором я никогда не слышал? Есть ли этому объяснение?

Ура! =)

Обновление :

Как любезно заметил @Graham, r4 (альтернативно v1) - это регистр переменной, который следует сохранить. Однако в ссылке , приведенной в его ответе, документация ARM использует регистр v1, сначала сохраняя его результат в стеке вместе со значением другого сохраненного регистра:

STMDB sp!,{v1,lr}
LDR v1,[a2,#0]

, а затем извлекая их значения. . Когда я компилирую этот код, он вылетает так же, как и мой оригинал, но

STMDB sp!,{v1,lr}
LDR v2,[a2,#0]

нет (обратите внимание на v2 вместо v1).

5
задан kristianp 2 May 2012 в 04:43
поделиться