почему адрес инструкции ARM не совпадает с моей средой ARM?

Моя среда ARM

root@linaro-developer:~# uname -a Linux linaro-developer 3.2.0 #7 SMP Thu Feb 28 16:20:18 PST 2013 armv7l armv7l armv7l GNU/Linux

И моя сборка

.section .text
.global _start
_start:
        .code 32
        #Thumb-Mode on
        add r6, pc, #1
        bx r6
        .code 16
        sub r4, r4, r4
        mov r0, r4
        ldr r2, =0x80047dbc
        blx r2
        ldr r2, =0x80047a0c
        blx r2

Однако, когда я пытаюсь выполнить отладку с помощью gdb, компьютер не переходит в состояние sub r4, r4, r4 gdb

(gdb) x/3i $pc
=> 0x83c8: add r6, pc, #1
   0x83cc:        bx r6     ;r6 = 0x83d1
   0x83d0: stcne 11, cr1, [r0], #-144 ; 0xffffff70
(gdb) x/3i 0x83d1
   0x83d1: subs r4, r4, r4
   0x83d3: adds r0, r4, #0
   0x83d5: ldr r2, [pc, #4] ; (0x83dc)

subs r4, r4, r4 адрес 0x83d1 0x83d1 не выровнен

Почему мой ассемблерный код находится по невыровненному адресу?


person 장석인    schedule 22.02.2015    source источник
comment
ПК переходит на 0x83d0, а затем на 0x83d2 (большой палец). Однако я хочу выполнить «subs r4, r4, r4». Что я должен делать? Когда я выполняю свой ассемблерный код, происходит «Сбой сегмента».   -  person 장석인    schedule 22.02.2015
comment
Каков адрес доступа, вызвавшего ошибку?   -  person Chris Stratton    schedule 22.02.2015
comment
(gdb) x/3i $pc => 0x83c8: добавить r6, pc, #1 0x83cc: bx r6 0x83d0: stcne 11, cr1, [r0], #-144 ; 0xffffff70 (gdb) ni Не удается получить доступ к памяти по адресу 0x0 0x000083cc в ?? () (gdb) si 0x000083d0 в ?? () (gdb) x/3i $pc => 0x83d0: stcne 11, cr1, [r0], #-144 ; 0xffffff70 0x83d4: ldrmi r4, [r0, r1, lsl #20] 0x83d8: ldrmi r4, [r0, r1, lsl #20] (gdb) ni 0x000083d2 в ?? () (gdb) x/3i $pc =› 0x83d2: bmi 0x4f45a 0x83d6: bmi 0x5a21e 0x83da: ldcvc 7, cr4, [r12, #576]! ; 0x240 (gdb) c Продолжение. Программа получила сигнал SIGSEGV, ошибка сегментации. 0x80047dbc в ?? ()   -  person 장석인    schedule 22.02.2015
comment
Извините, посмотрите, этот след такой сложный :(   -  person 장석인    schedule 22.02.2015
comment
О, 0x80047dbc — это адрес prepare_kernel_cred. Почему этот адрес не отображается? Я проверяю этот адрес с помощью команды grep _cred /proc/kallsyms   -  person 장석인    schedule 22.02.2015
comment
Вы уверены, что можно войти в ядро ​​таким образом? Звучит немного подозрительно, поэтому было бы неудивительно, если бы он не был сопоставлен для пользовательского пространства. Кроме того, x - это не трассировка, а скорее команда проверки, и вам следует редактировать результаты в своем вопросе, а не публиковать их в виде комментариев.   -  person Chris Stratton    schedule 22.02.2015
comment
Зачем писать ассемблер в первую очередь? В отличие от 32-битного режима ARM, здесь не так много усиления при записи большого пальца.   -  person Jake 'Alquimista' LEE    schedule 25.02.2015


Ответы (1)


(Полный) процессор ARM может выполнять инструкции либо в состоянии исполнения ARM, либо в состоянии выполнения Thumb — грубо говоря, это разница между универсальностью полного 32-битного командного слова или эффективностью кода более ограниченного 16-битного.

При переходе к адресу, содержащемуся в регистре, у вас есть возможность установить состояние ARM или Thumb с помощью LSB содержимого регистра, что, по-видимому, и делает отлаживаемый код — переход к 0x83d1 установит состояние Thumb, но фактический адрес целевой инструкции будет 0x83d0, который выровнен по 16 битам.

Напротив, при переходе к немедленному смещению у вас нет возможности установить режим с помощью LSB, но вместо этого вы можете выбрать между B/BL, которые сохраняют состояние, или BX/BLX, которые его переключают.

Обратите внимание, что некоторые ядра ARM меньшего размера, предназначенные для только встроенного использования, поддерживают режим Thumb и не могут выполнять инструкции ARM.

person Chris Stratton    schedule 22.02.2015
comment
Обратите внимание, что сам регистр ПК всегда содержит правильно выровненный адрес (и вы получите ошибку, если это не так) - младший бит значения, записанного на ПК в инструкции взаимодействия, имеет значение. . Фактический статус заканчивается битом T CPSR. Конечно, то, как gdb решит представлять вещи, может быть другим вопросом. - person Notlikethat; 22.02.2015
comment
Код расположен по адресу 0x83d0, а не 0x83d1 (хотя ваш отладчик услужливо отображает его по замаскированному адресу выравнивания, полученному из вашей записи). Это не работает? Что произойдет, если вы проследите это? - person Chris Stratton; 22.02.2015