Подтвердить что ты не робот

Недопустимая константа после исправления?

По какой-то причине, когда я пытаюсь скомпилировать этот бит кода, компилятор говорит syscall.s:72:invalid constant (0x172) after fixup:

.globl _mach_msg_trap$MACH
_mach_msg_trap$MACH:
    stmfd sp!, {r4,r7}
    mov r7, #370 /* this is line 72 */
    svc 0
    ldmfd sp!, {r4, r7}
    bx lr

Я не знаю, почему он это делает. Когда я помещаю меньшую константу в r7, она работает нормально. Но с более высокими номерами он выплевывает эту ошибку. Я временно исправил это, выполнив mov r7, #300 и add r7, #70, что обеспечивает желаемый эффект. Однако не уверен, что вызвало ошибку.

4b9b3361

Ответ 1

Инструкция ARM может загружать только ограниченный диапазон мгновенных значений с помощью mov. Проблема в том, что значение должно быть закодировано в самой команде mov. Поскольку все инструкции ARM имеют 32-разрядную ширину, исходная команда, настроенная до ARMv5, имела всего 8 + 4 бит для кодирования непосредственных. При первом 8-битном состоянии может быть загружено любое 8-битное значение int в диапазоне 0-255, а 4 бит - вправо с шагом 2 между 0 и 30.

Таким образом, вы можете загружать такие значения, как:

#0
#122
#121 ror #24 = 30976
#230 ror #12 = 241172480

Но, # 370 не загружается с помощью этой схемы, для этого потребуется нечто вроде #185 ror #31, которое невозможно.

Существует два способа загрузки вашего непосредственного значения.

  • Как вы это уже решили, построив значение за несколько шагов.
  • Загружая значение из памяти с помощью ldr: ldr r7,=#370 Затем ассемблер создаст константный пул и загрузит значение отсюда через pc-относительную адресацию.

Обычно вам нужно создавать константы с двумя инструкциями, если это невозможно (или значение должно быть перемещено) используйте ldr.

Начиная с ARMv7 вы также можете использовать movw для загрузки любого 16-битного значения в нижней половине регистра при обнулении верхней половины и movt для загрузки другого 16-битного значения в верхнюю половину, не касаясь нижней половины.