编译时寄存器检查 Thumb-2 代码
Compile-time register checks for Thumb-2 code
在 Thumb-2 代码中,在大多数指令中不可能使用寄存器 8-15,而在 ARM 代码中这是可能的。因此,以下程序集给出运行时非法指令错误:
.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
有没有什么工具可以在编译时检查非法指令?
R0-R7
限制仅适用于 16 位 Thumb,不适用于 32 位 Thumb-2(参见 here). The 32-bit STR.W
has 4 bits for the register (encodings here)。事实上,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
(来自 here)。由于它是 64 位 ARM,问题不是它不支持 Thumb-2,而是你不能在你的程序中切换 AArch64 <-> AArch32。
一个问题是您在符号 main
处有 Thumb 代码,但没有将其注释为 Thumb 符号。因此,链接器不会设置符号地址的 lsb,因此在 运行 时,调用以 ARM 状态到达那里,随后在 Thumb 编码上阻塞。要解决这个问题,您需要添加 .thumb_func
annotation:
...
.globl main
.thumb_func
main:
...
有了它,当您 运行 从该代码的末尾进入任何 code/data/unmapped 页面时,它很可能仍然因未定义的指令或段错误而崩溃。您实际上需要从 main
.
return
您最初的假设是不正确的,因为如果它是您怀疑的寄存器使用问题,它甚至不会assemble。 "tool that can be used to check for illegal instructions at compile time"是assembler.
在 Thumb-2 代码中,在大多数指令中不可能使用寄存器 8-15,而在 ARM 代码中这是可能的。因此,以下程序集给出运行时非法指令错误:
.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
有没有什么工具可以在编译时检查非法指令?
R0-R7
限制仅适用于 16 位 Thumb,不适用于 32 位 Thumb-2(参见 here). The 32-bit STR.W
has 4 bits for the register (encodings here)。事实上,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
(来自 here)。由于它是 64 位 ARM,问题不是它不支持 Thumb-2,而是你不能在你的程序中切换 AArch64 <-> AArch32。
一个问题是您在符号 main
处有 Thumb 代码,但没有将其注释为 Thumb 符号。因此,链接器不会设置符号地址的 lsb,因此在 运行 时,调用以 ARM 状态到达那里,随后在 Thumb 编码上阻塞。要解决这个问题,您需要添加 .thumb_func
annotation:
...
.globl main
.thumb_func
main:
...
有了它,当您 运行 从该代码的末尾进入任何 code/data/unmapped 页面时,它很可能仍然因未定义的指令或段错误而崩溃。您实际上需要从 main
.
您最初的假设是不正确的,因为如果它是您怀疑的寄存器使用问题,它甚至不会assemble。 "tool that can be used to check for illegal instructions at compile time"是assembler.