9

我想为我的测试夹具的测试导致 ARM Cortex-M3 未定义指令异常。IAR 编译器通过内联汇编支持这一点,如下所示:

asm("udf.w #0");

不幸的是,GNU CC 内联汇编器不知道 NXP LPC177x8x 的这个操作码。它写入诊断:

ccw3kZ46.s:404: Error: bad instruction `udf.w #0'

如何创建导致未定义指令异常的函数?

4

4 回答 4

11

基于Masta79的回答:

ARMv7-M 架构参考手册 - ARM DDI 0403D(文档占位符,需要注册)中列出了“永久未定义”编码。编码为 0xf7fXaXXX(忽略“X”)。当然指令获取是小端的,所以(未经测试):

asm volatile (".word 0xf7f0a000\n");

应该在任何 ARMv7-M 或更高版本的处理器上产生保证的未定义指令。

于 2013-04-18T15:28:05.847 回答
8

一些额外的信息...

GCC 的内置函数之一是

无效__builtin_trap(无效)

该函数会导致程序异常退出。GCC 通过使用依赖于目标的机制(例如故意执行非法指令)或调用 abort 来实现此功能。使用的机制可能因版本而异,因此您不应依赖任何特定的实现。

它对ARMv7 的实现是

(define_insn "trap"
  [(trap_if (const_int 1) (const_int 0))]
  ""
  "*
  if (TARGET_ARM)
    return \".inst\\t0xe7f000f0\";
  else
    return \".inst\\t0xdeff\";
  "
  [(set (attr "length")
    (if_then_else (eq_attr "is_thumb" "yes")
              (const_int 2)
              (const_int 4)))
   (set_attr "type" "trap")
   (set_attr "conds" "unconditional")]
)

因此,对于 ARM 模式,gcc 将生成0x7f000f0 (f0 00 f0 07),对于其他模式0xdeff (ff de)(反汇编/调试时会派上用场)。

另请注意

these encodings match the UDF instruction that is defined in the most
recent edition of the ARM architecture reference manual.

Thumb: 0xde00 | imm8  (we chose 0xff for the imm8)
ARM: 0xe7f000f0 | (imm12 << 8) | imm4  (we chose to use 0 for both imms)

对于生成的LLVM __builtin_trap值是0xe7ffdefe0xdefe

case ARM::TRAP: {
  // Non-Darwin binutils don't yet support the "trap" mnemonic.
  // FIXME: Remove this special case when they do.
  if (!Subtarget->isTargetDarwin()) {
    //.long 0xe7ffdefe @ trap
    uint32_t Val = 0xe7ffdefeUL;
    OutStreamer.AddComment("trap");
    OutStreamer.EmitIntValue(Val, 4);
    return;
  }
  break;
}
case ARM::tTRAP: {
  // Non-Darwin binutils don't yet support the "trap" mnemonic.
  // FIXME: Remove this special case when they do.
  if (!Subtarget->isTargetDarwin()) {
    //.short 57086 @ trap
    uint16_t Val = 0xdefe;
    OutStreamer.AddComment("trap");
    OutStreamer.EmitIntValue(Val, 2);
    return;
  }
  break;
}
于 2015-01-13T10:48:15.360 回答
7

永久未定义指令的 thumb-16 版本是0xDExx. 因此,您可以在代码中执行此操作以触发异常:

.inst 0xde00

参考:ARMv7-M 架构参考手册,第 A5.2.6 节。

(请注意,0xF7Fx、0xAxxx 编码也是永久未定义的,而是一条 32 位指令。)

于 2014-06-08T21:42:27.463 回答
6

[1]中有不同的官方未定义指令(查找UDF;.下面可以替换为任何十六进制数字):

  • 0xe7f...f.- ARM 或 A1 编码(ARMv4T、ARMv5T、ARMv6、ARMv7、ARMv8)
  • 0xde..- Thumb 或 T1 编码(ARMv4T、ARMv5T、ARMv6、ARMv7、ARMv8)
  • 0xf7f.a...- Thumb2 或 T2 编码(ARMv6T2、ARMv7、ARMv8)
  • 0x0000....- ARMv8-A 永久未定义

还有其他的,但这些可能是面向未来的。

至于生成触发它的代码,您可以使用.shortor .word,如下所示:

  • asm volatile (".short 0xde00\n");/* 拇指非法指令 */
  • asm volatile (".word 0xe7f000f0\n");/* arm 非法指令 */
  • asm volatile (".word 0xe7f0def0\n");/* arm+thumb 非法指令 */

请注意,最后一个将在 thumb 上下文中解码为0xdef00xe7f0因此也会导致未定义的指令异常。

[1] http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.subset.architecture.reference/index.html

[2] DDI0487D_b_armv8_arm.pdf

于 2015-11-16T14:18:31.427 回答