是否可以从机器代码中检测CPU架构?

时间:2016-06-27 13:53:09

标签: assembly x86 arm x86-64

假设有两种可能的架构,ARM和x86。 有没有办法检测代码运行的系统,从汇编/机器代码中实现这样的事情?

if (isArm)
    jmp to arm machine code
if (isX86)
    jmp to x86 machine code

我知道ARM机器代码与x86机器代码有很大不同。我正在考虑的是一些精心设计的汇编指令,它们会产生相同的二进制机器代码。

3 个答案:

答案 0 :(得分:17)

假设您已经处理了所有其他差异 1 并且您还在编写一个小型多语言蹦床,您可以使用这些操作码:

EB 02 00 EA

当放在地址0时,对于ARM(非拇指),转换为:

00000000: b 0xbb4
00000004: ...

但是对于x86(实模式),转换为:

0000:0000 jmp 04h
0000:0002 add dl, ch
0000:0004 ...

然后,您可以将更详细的x86代码放在地址04h,将ARM代码放在地址0bb4h。

当然,重新定位基地址时,请务必重新定位跳转目标。

1 例如,ARM starts at address 0而x86从地址0fffffff0h开始,因此您需要特定的硬件/固件支持来抽象引导地址。

答案 1 :(得分:2)

http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ddi0363g/Beijdcef.html

https://electronics.stackexchange.com/a/232934

How to setup ARM interrupt vector table branches in C or inline assembly?

http://osnet.cs.nchu.edu.tw/powpoint/Embedded94_1/Chapter%207%20ARM%20Exceptions.pdf

ARM Undefined Instruction error

ARM装配不是我的专业领域,但我已经在x86装配中编程了很多。我记得我和大学里的家庭作业有同样的问题。我找到的解决方案是中断06h(http://webpages.charter.net/danrollins/techhelp/0103.HTMhttps://es.wikipedia.org/wiki/Llamada_de_interrupci%C3%B3n_del_BIOS#Tabla_de_interrupciones)。每次微处理器尝试执行未知指令时都会触发此中断("无效操作码")。

当找到无效的操作码时,8086被卡住了,因为IP(指令指针)返回到同一个无效指令,它尝试重新执行它,这个循环阻碍了程序的执行。

从80286中断开始06h被触发,因此程序员可以处理无效的操作码案例。

中断06h有助于检测CPU架构,只需尝试执行x64操作码,如果中断06h被触发,CPU就无法识别它,所以它是x86,否则它是x64。

此技术还可用于检测微处理器的类型:

  • 尝试执行80286指令,如果未触发中断06h,则CPU至少为8286.
  • 尝试执行80386指令,如果未触发中断06h,则CPU至少为8386.
  • 依旧......

http://mtech.dk/thomsen/program/ioe.php

https://software.intel.com/en-us/articles/introduction-to-x64-assembly

答案 2 :(得分:1)

在装配或机器代码中是不可能的,因为机器代码将取决于架构。因此,必须首先将if语句编译为ARM或x86。如果它编译为ARM,则无法在没有模拟器的情况下在x86上运行,如果编译为x86,则在没有模拟器的情况下无法在ARM上运行。

如果你在模拟器中运行代码,那么代码基本上是在为其编译的CPU的虚拟版本中运行的。根据模拟器的不同,您可能会或可能无法检测到您在模拟器上运行。并且根据仿真器,如果仿真器允许您的代码检测到您在仿真器上运行,则可能无法检测到底层CPU和/或OS(例如,您可能无法检测到x86仿真器正在x86或ARM上运行。

现在,如果您非常幸运,您可能会发现两种CPU架构,其中一个架构的条件分支或条件goto指令在您的代码中执行某些有用的操作,或者在其他架构中执行任何操作,反之亦然。因此,如果是这种情况,您可以构建一个可以在两种不同的CPU架构上运行的二进制可执行文件。

多架构二进制文件在现实生活中的工作原理。

在现实生活中,多架构二进制文件实际上是两个具有共享资源(图标,图像等)的完整程序,程序二进制格式包括一个标题或前导码,用于告诉操作系统支持哪些CPU以及在哪里找到{ {1}}每个CPU的功能。

我能想到的最好的历史案例之一是Mac OS。 Mac改变了CPU两次:首先从68k改为PowerPC,然后从PowerPC改为x86。在每个阶段,他们必须提出一种文件格式,其中包含两个CPU架构的二进制可执行文件。

关于实际可执行文件的说明

现实生活中的程序几乎从不是原始的二进制可执行文件。二进制代码始终包含在包含元数据和资源的另一种格式中。例如,Windows使用PE格式,Linux使用ELF。但是一些操作系统支持多种类型的可执行容器(尽管实际上二进制机器代码可以是相同的)。例如,Linux传统上支持ELF,COFF和ECOFF。