新指令可以设计为“传统兼容”,也可以不设计。
前一类的指令如下tzcnt http://www.felixcloutier.com/x86/TZCNT.html or xacquire
具有在旧架构中生成有效指令的编码:tzcnt
被编码为rep bsf http://www.felixcloutier.com/x86/BSF.html and xacquire
只是repne
.
语义当然不同。
大多数新指令属于第二类,AVX 就是一个流行的例子。
当CPU遇到无效或保留的编码时,它会生成#UD (for 不明确的) 异常 - 这是中断号 6。
Linux 内核设置了IDT http://wiki.osdev.org/Interrupt_Descriptor_Table条目为#UD早在entry_64.S http://elixir.free-electrons.com/linux/latest/source/arch/x86/entry/entry_64.S#L850:
idtentry invalid_op do_invalid_op has_error_code=0
入口点指向do_invalid_op
这是用宏生成的traps.c http://elixir.free-electrons.com/linux/latest/source/arch/x86/kernel/traps.c#L289:
DO_ERROR(X86_TRAP_UD, SIGILL, "invalid opcode", invalid_op)
宏观DO_ERROR
生成一个调用的函数do_error_trap
在同一个文件中(here http://elixir.free-electrons.com/linux/latest/source/arch/x86/kernel/traps.c#L282).
do_error_trap
uses fill_trap_info
(在同一个文件中,here http://elixir.free-electrons.com/linux/latest/source/arch/x86/kernel/traps.c#L201)创建一个siginfo_t
包含Linux信号信息的结构体:
case X86_TRAP_UD:
sicode = ILL_ILLOPN;
siaddr = uprobe_get_trap_addr(regs);
break;
从那里发生以下调用:
do_trap
in traps.c http://elixir.free-electrons.com/linux/latest/source/arch/x86/kernel/traps.c#L233
force_sig_info
in signal.c http://elixir.free-electrons.com/linux/latest/source/kernel/signal.c#L1171
specific_send_sig_info
in signal.c http://elixir.free-electrons.com/linux/latest/source/kernel/signal.c#L1140
最终调用信号处理程序SIGILL
的违规过程。
下面的程序是一个非常简单的例子,它生成一个#UD
BITS 64
GLOBAL _start
SECTION .text
_start:
ud2
我们可以用strace
检查运行该程序收到的信号
--- SIGILL {si_signo=SIGILL, si_code=ILL_ILLOPN, si_addr=0x400080} ---
+++ killed by SIGILL +++
正如预期的那样。
As 科迪·格雷评论 https://stackoverflow.com/questions/44750258/what-happens-when-you-execute-an-instruction-that-your-cpu-does-not-support#comment76501377_44750258,库通常不依赖于 SIGILL,而是使用CPU调度程序 https://software.intel.com/en-us/articles/intel-integrated-performance-primitives-intel-ipp-understanding-cpu-optimized-code-used-in-intel-ipp或明确检查指令是否存在。