我想为测试夹具的测试引起ARM Cortex-M3未定义指令异常。 IAR编译器支持使用内联汇编,如下所示:
asm(“udf.w#0”);
不幸的是,GNU CC内联汇编程序不知道NXP LPC177x8x的这个操作码。它写了诊断:
ccw3kZ46.s:404: Error: bad instruction `udf.w #0'
如何创建导致未定义指令异常的函数?
答案 0 :(得分:10)
以 Masta79 的答案为基础:
ARMv7-M架构参考手册中列出了“永久未定义”编码 - ARM DDI 0403D(documentation placeholder, registration required)。编码为0xf7fXaXXX(其中“X”被忽略)。当然,指令提取是小端的,所以(没有测试):
asm volatile (".word 0xf7f0a000\n");
应在任何ARMv7-M或更高版本的处理器上产生有保证的未定义指令。
答案 1 :(得分:6)
永久未定义指令的thumb-16版本为0xDExx
。因此,您可以在代码中执行此操作以触发异常:
.short 0xde00
参考:ARMv7-M架构参考手册,A5.2.6节。
(注意,0xF7Fx,0xAxxx编码也是永久未定义的,但是是32位指令。)
答案 2 :(得分:6)
一些额外信息......
GCC的builtins之一是
void __builtin_trap(void)
此功能导致程序异常退出。 GCC通过使用依赖于目标的机制(,例如故意执行非法指令)或通过调用abort来实现此功能。 所使用的机制可能因版本而异,因此您不应依赖任何特定实现。
(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
个值为0xe7ffdefe
和0xdefe
:
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;
}
答案 3 :(得分:5)
[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永久未定义还有其他人,但这些可能是未来的证据。
至于生成触发它的代码,您可以使用.short
或.word
,如下所示:
asm volatile (".short 0xde00\n");
/ *拇指非法指示* / asm volatile (".word 0xe7f000f0\n");
/ *非法指令* / asm volatile (".word 0xe7f0def0\n");
/ * arm + thumb非法指示* / 请注意,最后一个将在拇指上下文中解码为0xdef0
,0xe7f0
,因此也会导致未定义的指令异常。
[1] http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.subset.architecture.reference/index.html
[2] DDI0487D_b_armv8_arm.pdf