Странное поведение ldr [pc, #value]

Я отлаживал код С++ (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 (8bytes +), это происходит и для других ldr-обычаев.

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

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

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

Ответ 1

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

Из ARM-ARM:

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

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

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

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

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

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