Странное поведение ldr [pc, #value] - PullRequest
11 голосов
/ 20 января 2010

Я отлаживал некоторый код на С ++ (WinCE 6 на платформе ARM), и я нахожу странное поведение:

    4277220C    mov         r3, #0x93, 30
    42772210    str         r3, [sp]
    42772214    ldr         r3, [pc, #0x69C]
    42772218    ldr         r2, [pc, #0x694]
    4277221C    mov         r1, #0
    42772220    ldr         r0, [pc, #0x688]

Строка 42772214 ldr r3, [pc, #0x69C] используется для получения некоторой константы из секции .DATA, по крайней мере, я так думаю.

Что странно, что согласно коду r2 должен заполняться памятью с адреса pc = 0x42772214 + 0x69C = 0x427728B0, но в соответствии с содержимым памяти, загруженным из 0x427728B8 (8 байтов +), это происходит и для других использований ldr.

Это вина отладчика или мое понимание ldr / pc? Еще одна проблема, которую я не получаю - почему доступ к разделу .data относится к исполняемому коду? Я нахожу это немного странным.

И еще одна проблема: я не могу найти синтаксис 1-й команды mov (любой может указать мне спецификацию типа для большого пальца (1C2))

Извините за описание, но я просто знакомлюсь со сборками.

1 Ответ

17 голосов
/ 20 января 2010

Это правильно. Когда для чтения используется pc, в режиме ARM смещение составляет 8 байтов, а в режиме большого пальца - 4 байта.

от АРМ-АРМ:

Когда инструкция читает ПК, значение чтения зависит от того, из какого набора инструкций оно поступило:

  • Для инструкции ARM считанное значение - это адрес инструкции плюс 8 байтов . Биты [1: 0] этого значения всегда равны нулю, поскольку инструкции ARM всегда выровнены по словам.
  • Для инструкции Thumb прочитанное значение - это адрес инструкции плюс 4 байта . Бит [0] этого значения всегда равен нулю, поскольку инструкции Thumb всегда выровнены наполовину.

Этот способ чтения с ПК в основном используется для быстрой, независимой от позиции адресации соседних инструкций и данных, включая независимое от позиции ветвление внутри программы.

Есть 2 причины для относительной к ПК адресации.

  1. Позиционно-независимый код, который есть в вашем случае.
  2. Возьмите несколько сложных констант поблизости, которые нельзя записать в одной простой инструкции, например, mov r3, #0x12345678 невозможно выполнить в 1 инструкции, поэтому компилятор может поместить эту константу в конец функции и использовать, например, ldr r3, [pc, #0x50] чтобы загрузить его.

Я не знаю, что означает mov r3, #0x93, 30. Вероятно, это mov r3, #0x93, rol 30 (что дает 0xC0000024)?

...