Регистр во время компиляции проверяет наличие кода Thumb-2

В коде Thumb-2 невозможно использовать регистры 8-15 в большинстве инструкций, в то время как в коде ARM это возможно. Следовательно, следующая сборка выдает ошибку Illegal Instruction во время выполнения:

        .syntax unified
        .fpu    vfp
        .thumb
        .text
        .globl  main
main:
        str r12,[sp,#-4]    @ r12 is too high, source register is 3 bits wide

Однако я не получаю предупреждения во время компиляции, хотя я использую -Wall:

pi@rasppi:~/ctests$ arm-linux-gnueabihf-as -Wall -o high.o high.s 
ARM GAS  high.s                         page 1


   1                                    .syntax unified
   2                                    .fpu    vfp
   3                                    .thumb
   4                                    .text
   5                                    .globl  main
   6                            main:
   7 0000 4DF804CC                      str r12,[sp,#-4]
pi@rasppi:~/ctests$ arm-linux-gnueabihf-gcc -Wall -o high high.o 
pi@rasppi:~/ctests$ ./high 
Illegal instruction
pi@rasppi:~/ctests$ file high
high: ELF 32-bit LSB executable, ARM, EABI5 version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux-armhf.so.3, for GNU/Linux 2.6.32, BuildID[sha1]=c9d90a7d6386bf97a18f9da87a7b2ce422402659, not stripped

Есть ли какой-либо инструмент, который можно использовать для проверки недопустимых инструкций во время компиляции?


person Community    schedule 18.09.2016    source источник


Ответы (2)


Одна проблема заключается в том, что у вас есть код Thumb в символе main, но вы не аннотировали его как символ Thumb. Таким образом, компоновщик не устанавливает младший бит адреса символа, поэтому во время выполнения вызов попадает туда в состоянии ARM и впоследствии подавляется кодировкой Thumb. Чтобы решить эту проблему, вам нужно добавить аннотацию .thumb_func:

...
.globl main
.thumb_func
main:
...

При этом весьма вероятно, что все равно произойдет сбой либо с неопределенной инструкцией, либо с ошибкой сегментации, когда вы запустите конец этого кода на любую следующую код/данные/неотображенную страницу. Вам действительно нужно вернуться из main.

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

person Notlikethat    schedule 18.09.2016
comment
Спасибо! Это работает, когда я добавляю bx lr в конце main для возврата. - person ; 18.09.2016

Ограничение R0-R7 применяется только к 16-битному Thumb, а не к 32-битному Thumb-2 (см. здесь). 32-битный STR.W имеет 4 бита для регистра (кодировки здесь). На самом деле GCC действительно генерирует инструкцию STR.W (4DF804CC).

Незаконная инструкция, скорее всего, вызвана тем, что ваша цель не поддерживает Thumb-2. Вы должны правильно определить свою цель (-mthumb, -march, -mcpu, -mfpu,...), чтобы ассемблер знал, что можно и что нельзя использовать.

Теперь, когда вы добавили, что используете Raspberry Pi 3, модель B, я бы попробовал эти флаги: -march=armv8-a+crc -mtune=cortex-a53 -mfpu=crypto-neon-fp-armv8 -mfloat-abi=hard (из здесь). Поскольку это 64-битный ARM, проблема не в том, что он не поддерживает Thumb-2, а в том, что вы не можете переключать AArch64 ‹-> AArch32 внутри своей программы.

person Andrea Biondo    schedule 18.09.2016
comment
Ясно спасибо. Как найти правильные настройки для -march и -mcpu? Вот мой /proc/cpuinfo; это Raspberry Pi 3, модель B. - person ; 18.09.2016
comment
@CamilStaps Я думаю, что проблема в этом случае может заключаться в том, что созданная вами программа является 64-битной программой ARM. Ваш ассемблер может позволить вам переключиться в режим большого пальца внутри такой программы, но полученный код не будет работать. - person fuz; 18.09.2016
comment
@CamilStaps Добавлены флаги. Я полностью пропустил подсказку pi@rasppi... - person Andrea Biondo; 18.09.2016
comment
@CamilStaps Я имею в виду, что ядро ​​не может не поддерживать thumb2. OP, вероятно, просто нужно указать своему компилятору сгенерировать 32-битную программу; хотя не уверен, как. - person fuz; 18.09.2016
comment
@FUZxxl Ну, можно скомпилировать для 32-битного процессора ARM, чтобы компилятор сгенерировал код AArch32 и связал его с 32-битным исполняемым файлом, ОС сделает все остальное. Однако не уверен, как это связано с FPU и расширениями. - person Andrea Biondo; 18.09.2016
comment
@AndreaBiondo Я думаю, вам просто нужно передать флаг, похожий на -m32 на x86, чтобы компилятор скомпилировал 32-битный двоичный файл. Я не думаю, что установка 32-битного процессора поможет, я думаю, вы просто получите сообщение «процессор не поддерживает aarch64». - person fuz; 18.09.2016
comment
AArch64 почти наверняка не имеет значения — 32-битная (то есть arm-*) цепочка инструментов, которая используется здесь, не способна генерировать или связывать 64-битный код. Кроме того, стандартное пользовательское пространство Raspberry Pi 3 в любом случае полностью 32-битное. - person Notlikethat; 18.09.2016
comment
@Notlikethat Подожди, что? Raspberry Pi 3 — это 64-битный процессор. Почему, черт возьми, они не поставляют с ним 64-битный набор инструментов? - person fuz; 18.09.2016
comment
@FUZxxl Потому что у них есть единый образ пользовательского пространства для всех 3 поколений плат, и, насколько я знаю, 3 все еще работает в основном с тем же 32-битным ядром, что и 2 - если вы хотите запускать 64-битное программное обеспечение, у вас есть установить свое собственное Ядро AArch64 и пользовательское пространство. - person Notlikethat; 18.09.2016
comment
Спасибо, и извините за поздний ответ. Сейчас я собираю с этими флагами (без -mtune, который не распознан) и линкуюсь с этими флагами (с -mtune), но все равно не работает. Я получаю недопустимую инструкцию на 0x10932 vcgt.s8 q8, <illegal reg q6.5>, #0, но не могу найти эту инструкцию с помощью objdump. Любая идея, что может пойти не так? - person ; 18.09.2016